RelationService

The RelationService is pretty awesome as it allows you to create relations between objects that would otherwise have no obvious connection.

Browse the API documentation for IRelationService interface.

  • Namespace: Umbraco.Core.Services

  • Assembly: Umbraco.Core.dll

Getting the service

When you are using an Umbraco controller class (Such as SurfaceController or RenderMvcController) you have access to the RelationService through the ServiceContext:

using System.Web.Mvc;
using Umbraco.Web.Models;
using Umbraco.Web.Mvc;

namespace Doccers.Core.Controllers
{
    public class HomeController : RenderMvcController
    {
        public ActionResult Home(ContentModel model)
        {
            var rs = Services.RelationService;

            return CurrentTemplate(model);
        }
    }
}

You can also use the RelationService in any other class by injecting its interface:

using Umbraco.Core.Composing;
using Umbraco.Core.Services;

namespace Doccers.Core.Components
{
    public class RelationComponent : IComponent
    {
        private readonly IRelationService _relationService;

        public RelationComponent(IRelationService relationService)
        {
            _relationService = relationService;
        }

        public void Initialize() { }

        public void Terminate() { }
    }
}

Methods

AreRelated(int parentId, int childId, string relationTypeAlias)

Checks if two items are related.

Returns bool.

AreRelated(IUmbracoEntity parent, IUmbracoEntity child, string relationTypeAlias)

Checks if two items are related.

Returns bool.

AreRelated(int parentId, int childId)

Checks if two items are related.

Returns bool.

Delete(IRelation relation)

Deletes a relation.

Returns void.

Delete(IRelationType relationType)

Deletes a relation type.

Returns void.

DeleteRelationsOfType(IRelationType relationType)

Deletes relation of the specified relation type.

Returns void.

GetAllRelations(params int[] ids)

Gets a collection of Umbraco.Core.Models.Relation objects. Optional array of integer ids to return relations for.

Returns IEnumerable<IRelation>.

GetAllRelationsByRelationType(RelationType relationType)

Gets a collection of Umbraco.Core.Models.Relation objects by their relation type.

Returns IEnumerable<IRelation>.

GetAllRelationsByRelationType(int relationTypeId)

Gets a collection of Umbraco.Core.Models.Relation objects by their relation type id.

Returns IEnumerable<IRelation>.

GetAllRelationTypes(params int[] ids)

Gets a collection of Umbraco.Core.Models.Relation objects. Optional array of integer ids to return relationtypes for.

Returns IEnumerable<IRelationType>.

GetByChild(IUmbracoEntity child)

Gets a collection of Umbraco.Core.Models.Relation objects by their child entity.

Returns IEnumerable<IRelation>.

GetByChild(IUmbracoEntity child, string relationTypeAlias)

Gets a collection of Umbraco.Core.Models.Relation objects their child entity and relation type alias.

Returns IEnumerable<IRelation>.

GetByChildId(int id)

Gets a collection of Umbraco.Core.Models.Relation objects by their child id.

Returns IEnumerable<IRelation>.

GetById(int id)

Gets a Umbraco.Core.Models.Relation object by its id.

Returns IRelation.

GetByParent(IUmbracoEntity parent, string relationTypeAlias)

Gets a collection of Umbraco.Core.Models.Relation objects by their parent entity and relation type alias.

Returns IEnumerable<IRelation>.

GetByParent(IUmbracoEntity parent)

Gets a collection of Umbraco.Core.Models.Relation objects by their parent entity.

Returns IEnumerable<IRelation>.

GetByParentId(int id)

Gets a collection of Umbraco.Core.Models.Relation objects by their parent id.

Returns IEnumerable<IRelation>.

GetByParentOrChildId(int id, string relationTypeAlias)

Gets a collection of Umbraco.Core.Models.Relation objects by their parent or child id and relation type alias.

Returns IEnumerable<IRelation>.

Using this method will get you all relations regards of it being a child or parent relation.

GetByParentOrChildId(int id)

Gets a collection of Umbraco.Core.Models.Relation objects by their parent or child id.

Returns IEnumerable<IRelation>.

Using this method will get you all relations regards of it being a child or parent relation.

GetByRelationTypeAlias(string relationTypeAlias)

Gets a collection of Umbraco.Core.Models.Relation objects by their relation type alias.

Returns IEnumerable<IRelation>.

GetByRelationTypeId(int relationTypeId)

Gets a collection of Umbraco.Core.Models.Relation objects by the id of their relation type.

Returns IEnumerable<IRelation>.

GetByRelationTypeName(string relationTypeName)

Gets a collection of Umbraco.Core.Models.Relation objects by the name of their relation type.

Returns IEnumerable<IRelation>.

GetChildEntitiesFromRelations(IEnumerable relations)

Gets the child objects from a collection of IRelation as a collection of Umbraco.Core.Models.Entities.IUmbracoEntity.

Returns IEnumerable<IUmbracoEntity>.

GetChildEntityFromRelation(IRelation relation)

Gets the child object from a relation as an Umbraco.Core.Models.Entities.IUmbracoEntity object.

Returns IUmbracoEntity.

GetEntitiesFromRelation(IRelation relation)

Gets the parent and child objects from a relation as a System.Tuple with Umbraco.Core.Models.Entities.IUmbracoEntity.

Returns Tuple<IUmbracoEntity, IUmbracoEntity>.

GetEntitiesFromRelations(IEnumerable relations)

Gets the parent and child objects from a collection of relations as a list of Umbraco.Core.Models.Entities.IUmbracoEntity objects.

Returns IEnumerable<Tuple<IUmbracoEntity, IUmbracoEntity>>.

GetParentEntitiesFromRelations(IEnumerable relations)

Gets the parent objects from a collection of relations as a collection of Umbraco.Core.Models.Entities.IUmbracoEntity.

Returns IEnumerable<IUmbracoEntity>.

GetParentEntityFromRelation(IRelation relation)

Gets the parent object from a relation as an Umbraco.Core.Models.Entities.IUmbracoEntity object.

GetRelationTypeByAlias(string alias)

Gets an relation by its alias.

Returns IRelationType.

GetRelationTypeById(Guid id)

Gets a relation type by its Id

Returns IRelationType.

GetRelationTypeById(int id)

Gets a relation type by its id.

Returns IRelationType.

HasRelations(IRelationType relationType)

Checks if any relations exist for the specified relation type.

Returns bool.

IsRelated(int id)

Checks if any relations exist for the specified id.

Returns void.

Relate(int parentId, int childId, IRelationType relationType)

Relates two objects by their ids using the specified relation type.

Returns IRelation.

Relate(IUmbracoEntity parent, IUmbracoEntity child, IRelationType relationType)

Relates two IUmbracoEntity objects using the specified relation type.

Returns IRelation.

Relate(IUmbracoEntity parent, IUmbracoEntity child, string relationTypeAlias)

Relates two IUmbracoEntity objects using the specified relation type alias.

Returns IRelation.

Relate(int parentId, int childId, string relationTypeAlias)

Relates two IUmbracoEntity objects using the specified relation type alias.

Returns IRelation.

Save(IRelation relation)

Saves a relation.

Returns Void.

Save(IRelationType relationType)

Saves a relation type.

Returns Void.

Examples

Below you will examples using the RelationService.

Automatically relate to root node

Odd example, I know.. but why not?

To perform the said task we need a component in which we can register to the ContentService.Published event:

(You can read more about composing Umbraco here)

using System.Linq;
using Umbraco.Core.Composing;
using Umbraco.Core.Events;
using Umbraco.Core.Services;
using Umbraco.Core.Services.Implement;

namespace Doccers.Core.Components
{
    public class RelationComponent : IComponent
    {
        private readonly IRelationService _relationService;

        public RelationComponent(IRelationService relationService)
        {
            _relationService = relationService;
        }

        public void Initialize()
        {
            ContentService.Published += ContentService_Published;
        }

        private void ContentService_Published(IContentService sender,
            ContentPublishedEventArgs e)
        {
            // Should never be null, to be honest.
            var home = sender.GetRootContent()?.FirstOrDefault();
            if (home == null) return;

            // Get the relation type by alias
            var relationType = _relationService.GetRelationTypeByAlias("homesick");
            if (relationType == null) return;

            foreach (var entity in e.PublishedEntities
                .Where(x => x.Id != home.Id))
            {
                // Check if they are already related
                if (!_relationService.AreRelated(home.Id, entity.Id))
                {
                    // If not then let us relate the currenty entity to home
                    _relationService.Relate(home.Id, entity.Id, relationType);
                }
            }
        }

        public void Terminate() {
          //unsubscribe during shutdown
          ContentService.Published -= ContentService_Published;
        }
    }
}

To have Umbraco recognize our component we need to register it in a composer:

using Doccers.Core.Components;
using Umbraco.Core;
using Umbraco.Core.Composing;

namespace Doccers.Core.Composers
{
    [RuntimeLevel(MinLevel = RuntimeLevel.Run)]
    public class RelationComposer : IUserComposer
    {
        public void Compose(Composition composition)
        {
            composition.Components().Append<RelationComponent>();
        }
    }
}

If I know Save and Publish my Products node I get the following result:

Relations

Cool! Now let us try and fetch the data from an API.

using System;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Umbraco.Core.Services;
using Umbraco.Web.WebApi;

namespace Doccers.Core.Controllers.Http
{
    public class RelationsController : UmbracoApiController
    {
        private readonly IRelationService _relationService;

        public RelationsController(IRelationService relationService)
        {
            // Alternatively you could also access
            // the service via the service context:
            // _relationService = Services.RelationService;
            _relationService = relationService;
        }

        [HttpGet]
        public HttpResponseMessage GetByRelationTypeAlias(string alias)
        {
            var relationType = _relationService.GetRelationTypeByAlias(alias);
            if (relationType == null)
                return Request.CreateResponse(HttpStatusCode.BadRequest,
                    "Invalid relation type alias");

            var relations = _relationService.GetAllRelationsByRelationType(relationType.Id);
            var content = relations.Select(x => Umbraco.Content(x.ChildId))
                .Select(x => new Relation()
                {
                    Name = x.Name,
                    UpdateDate = x.UpdateDate
                });

            return Request.CreateResponse(HttpStatusCode.OK, content);
        }
    }
}

Notice the x => new Relation()? We need to make sure what we are returning can be serialized. Therefore the Relation class is:

[DataContract(Name = "relation")]
public class Relation
{
    [DataMember(Name = "name")]
    public string Name { get; set; }

    [DataMember(Name = "updateDate")]
    public DateTime UpdateDate { get; set; }
}

Browsing /umbraco/api/relations/getbyrelationtypealias?alias=homesick now returns the following:

Relations

If you want to do something similar to this it is recommended that you wrap a caching layer around it, as the RelationService queries the database directly.

Last updated