IInternalUrlConverter

Convert internal URLs into public ones with custom internal URL converter.

To convert internal URLs into public URLs to access data items on the website, you should:

  1. Create a custom internal URL converter by implementing the interface IInternalUrlConverter.
  2. Register the converter.

Note: The following sample code refers to the custom internal URL provider described in "Custom Internal URLs".

Creating a custom internal URL converter

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Composite.Core.Routing;
using Composite.Core.Types;
using Composite.Data;

namespace Demo
{
    public class CustomDataUrlConvert : IInternalUrlConverter
    {
        
        private readonly IEnumerable<string> _urlPrefixes;
        private readonly Type _type;
        private readonly Type _keyType;
        private readonly ConstructorInfo _dataReferenceConstructor;

        public CustomDataUrlConvert(string shortTypeName, Type type)
        {
            _urlPrefixes = new[] { shortTypeName + "(" };
            _type = type;
            _keyType = _type.GetKeyProperties().Single().PropertyType;

            _dataReferenceConstructor = typeof(DataReference<>).MakeGenericType(_type).GetConstructor(new[] { typeof(object) });
        }

        public IEnumerable<string> AcceptedUrlPrefixes
        {
            get { return _urlPrefixes; }
        }

        public string ToPublicUrl(string internalDataUrl, UrlSpace urlSpace)
        {
            object keyValue = ExtractKeyValue(internalDataUrl);
            if(keyValue == null) return null;

            var data = DataFacade.TryGetDataByUniqueKey(_type, keyValue);
            if(data == null) return null;

            var pageUrlData = DataUrls.TryGetPageUrlData(data.ToDataReference());
            return pageUrlData != null ? PageUrls.BuildUrl(pageUrlData, UrlKind.Public, urlSpace) : null;
        }

        private object ExtractKeyValue(string internalDataUrl)
        {
            int openBracketIndex = internalDataUrl.IndexOf("(", StringComparison.Ordinal);
            if (openBracketIndex < 0)
            {
                return null;
            }

            int closingBracketOffset = internalDataUrl.IndexOf(")", openBracketIndex + 1, StringComparison.Ordinal);
            if (closingBracketOffset < 0)
            {
                return null;
            }

            string dataIdStr = internalDataUrl.Substring(openBracketIndex + 1, closingBracketOffset - openBracketIndex - 1);

            object keyValue = ValueTypeConverter.Convert(dataIdStr, _keyType);

            if (keyValue == null || (keyValue is Guid && (Guid)keyValue == Guid.Empty))
            {
                return null;
            }

            return keyValue;
        }

        public IDataReference ToDataReference(string internalDataUrl)
        {
            object keyValue = ExtractKeyValue(internalDataUrl);
            if (keyValue == null) return null;

            return (IDataReference)_dataReferenceConstructor.Invoke(new [] { keyValue });
        }
    }
}

Download CustomDataUrlConverter.cs

Expand the source code for IInternalUrlConverter

Registering the internal URL converter

Now that you've created a custom internal URL converter, you need to register it. You can do it on the application startup:

using System.Linq;
using Composite.Core.Application;
using Composite.Core.Routing;
using Composite.Data;

namespace Demo
{
    [ApplicationStartup]
    public class Startup
    {
        public static void OnBeforeInitialize()
        {

        }

        public static void OnInitialized()
        {
            var newsDataType = DataFacade.GetAllInterfaces().FirstOrDefault(u => u.Name == "News");
            InternalUrls.Register(new CustomDataUrlConvert("news", newsDataType));
        }

    }
}
  
Important. Place the initialization code in onInitialized(). Code will throw an exception when accessing methods related to data façade in OnBeforeInitialize().

Using the sample

To test this sample:

  1. Create and add to the website the custom internal URL provider described in "Custom Internal URLs".
  2. In Visual Studio, create a class library project:
    1. referring the custom internal URL provider,
    2. and using the sample code above for the provider and the application startup.
  3. Build and copy the resulting DLL to ~/Bin on your website.
  4. Restart the server.

Now you can insert individual links to items of the data type in use, and because these internal links get converted, you click them on the published pages to view content of the items.

Requirements:

C1 CMS version 5.0 or later