<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Blog posts by Johan Björnfot</title><link href="http://world.optimizely.com" /><updated>2023-08-31T12:54:35.0000000Z</updated><id>https://world.optimizely.com/blogs/Johan-Bjornfot/</id> <generator uri="http://world.optimizely.com" version="2.0">Optimizely World</generator> <entry><title>Parallel Tasks and BackgroundContext</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2023/8/parallel-tasks-and-backgroundcontext/" /><id>&lt;p&gt;We have recently (CMS.Core 12.16.0) made a change to better support asynchronous async/await execution flows as well as isolation of service resolving from IOC container in parallel contexts.&lt;/p&gt;
&lt;p&gt;This change can affect code that spawns up multiple parallel tasks. Such code might face errors like &amp;ldquo;Cannot create a command without an existing connection&amp;rdquo; or &amp;ldquo;The connection is closed&amp;rdquo;. The reason for this is that to support asynchronous async/await execution is the database context &amp;ldquo;flowed&amp;rdquo; together with the other execution context. But as for async/await flows are the execution context also preserved through for example &lt;em&gt;Task.Run&lt;/em&gt; or &lt;em&gt;Task.Factory.StartNew &lt;/em&gt;calls. This has the consequence that if new tasks are created in parallel then multiple simultaneous tasks will share the same database context, which might cause problem since the database context is not thread-safe. This can for example lead to the exceptions mentioned earlier.&lt;/p&gt;
&lt;h2&gt;BackgroundContext&lt;/h2&gt;
&lt;p&gt;To support the scenarios where new tasks/threads are spawned up in parallel we have introduced a service &lt;em&gt;IBackgroundContextFactory&lt;/em&gt; (it was introduced in CMS.Core.12.16.0 but there is bug that has been resolved in CMS.Core.12.17.1 so that version or later is recommended). It has a single method like:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;    /// &amp;lt;summary&amp;gt;
    /// Used to create a new context that has its own scope for services and request caches.
    /// Recommended to use for background task/threads
    /// &amp;lt;/summary&amp;gt;
    public interface IBackgroundContextFactory
    {
        /// &amp;lt;summary&amp;gt;
        /// Creates a new context that has its own scope for services and request caches.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;returns&amp;gt;A disposable context.&amp;lt;/returns&amp;gt;
        IBackgroundContext Create();
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;The created context will contain an isolated context for the execution meaning it will have an own scoped &lt;em&gt;IServiceProvider&lt;/em&gt; (that will be disposed when the context is disposed) and an isolated execution context (including database context). The execution within this background context also supports asynchronous async/await execution.&lt;/p&gt;
&lt;p&gt;The scoped service provider will also ensure the services are preserved as long as the context. This protected from things like ObjectDisposedException which you prior to this could get if you created a parallel task within a http request (like an event handler to for example IContentEvents that starts a background task). Reason for the ObjectDisposedException is that the task will use the scoped container from the http request and then if the http request ends before the background task then you might get ObjectDisposedException.&lt;/p&gt;
&lt;h2&gt;Recommended usage&lt;/h2&gt;
&lt;p&gt;If you have code that spawn up new tasks/threads (like for example &lt;em&gt;Task.Run&lt;/em&gt;, &lt;em&gt;Task.Factory.StartNew&lt;/em&gt;, &lt;em&gt;Task.WhenAll, &lt;/em&gt;&lt;em&gt;Parallel.ForEach&lt;/em&gt; or unawaited tasks), then if the code to be executed in the task is accessing other services, then the recommendation is to create a background context for the thread. So, say for example you have code like:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;        var tasks = new List&amp;lt;Task&amp;gt;();
        foreach (var thing in things)
        {
            tasks.Add(Task.Run(() =&amp;gt;
            {
	           //Some code that run in parallel
            }));
        }

        Task.WaitAll(tasks.ToArray());
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then the suggestion would be to change it to:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;        var tasks = new List&amp;lt;Task&amp;gt;();
        foreach (var thing in things)
        {
            tasks.Add(Task.Run(() =&amp;gt;
            {
                using (var backgroundContext = _backgroundContextFactory.Create())
                //below is example on how to get a scoped service
                //ServiceLocator.Current and Injected&amp;lt;&amp;gt; also works with background context (even if usage of those are not recommended as best practice)
                var isolatedScopedService = backgroundContext.Service.Get&amp;lt;IAScopedService&amp;gt;();
                //Some code that run in parallel
            }));
        }

        Task.WaitAll(tasks.ToArray());
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So the recommendation is that the first statement within the task/thread should be to create a background context for the task to execute within.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt; that you do not need to (and should not) create a new background context within an &amp;ldquo;normal&amp;rdquo; async/await execution flow (that is when you are awaiting the tasks and not executing them in parallel). Because in that case is there only one thread executing simultaneously and, in that case, you do want the execution context (including database context) to flow between the potential different threads that are part of the asynchronous async/await execution flow.&lt;/p&gt;</id><updated>2023-08-31T12:54:35.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Upgrade to CMS 12, usage of upgrade-assistant-extensions</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2022/1/upgrade-to-cms-12-updates-to-upgrade-assistant-extensions/" /><id>&lt;p&gt;As you might now, there is an upgrade-assistant tool that can help the migration from an ASPNET project to an ASPNET core project, see &lt;a href=&quot;https://dotnet.microsoft.com/en-us/platform/upgrade-assistant&quot;&gt;upgrade-assistant&lt;/a&gt; with &lt;a href=&quot;https://github.com/dotnet/upgrade-assistant&quot;&gt;source&lt;/a&gt;. The tool will convert ASPNET projects to new .csproj style, change target framework and update packages. It then also contains some Roslyn analyzers and code fixers that changes some common code (like changing namespaces containing System.Web or replacing code like HttpContext.Current).&lt;/p&gt;
&lt;p&gt;There is also an optimizely extension &lt;a href=&quot;https://github.com/episerver/upgrade-assistant-extensions/tree/main/src/EpiSourceUpdater&quot;&gt;EPiSourceUpdater&lt;/a&gt; to the upgrade-assistant tool that includes code analyzers/codefixers that are specific to CMS/Commerce projects. The extension is being continuolsy updated so make sure you download the latest package from the &lt;a href=&quot;https://github.com/episerver/upgrade-assistant-extensions/releases&quot;&gt;Relase section&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Targeting net5&lt;/h2&gt;
&lt;p&gt;We are currently working on net6 support for CMS and Commerce but until that is released the upgrade need to target net5. The upgrade-assistant tool itself has been upgraded to net6 and that is what is used if you install the tool using dotnet cli. It seems that some of the built-in code analyzers/fixes will not apply if the project being upgraded is targeting net5, so my recommendation (until CMS support net6) is to instead of installing the upgrade-assistant tool, clone the &lt;a href=&quot;https://github.com/dotnet/upgrade-assistant&quot;&gt;upgrade-assistant&lt;/a&gt; repo and build it locally. The CLI tool is targeting both net5 and net6 so you can then run the executable from the net5 output folder.&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Step 1&lt;/h3&gt;
&lt;p&gt;Clone the upgrade-assistant repo and build it as described &lt;a href=&quot;https://github.com/dotnet/upgrade-assistant/blob/main/CONTRIBUTING.md#get-and-build-source-code&quot;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Step 2&lt;/h3&gt;
&lt;p&gt;Download latest CMS/Commerce extension package from &lt;a href=&quot;https://github.com/episerver/upgrade-assistant-extensions/releases&quot;&gt;here&lt;/a&gt; and unzip it to some location.&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Step 3&lt;/h3&gt;
&lt;p&gt;Open a cmd prompt and navigate to the output location of the cli build from step 1. Typically, &amp;lt;checkout location&amp;gt;\artifacts\bin\Microsoft.DotNet.UpgradeAssistant.Cli\Debug\net5.0&lt;/p&gt;
&lt;h3&gt;Step 4&lt;/h3&gt;
&lt;p&gt;To specify that the project you are upgrading should target net5 you need to run the following in the command prompt&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;set DefaultTargetFrameworks__LTS=net5.0&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 5&lt;/h3&gt;
&lt;p&gt;Now you can execute the upgrade-assistant tool from the command prompt like:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;Microsoft.DotNet.UpgradeAssistant.Cli upgrade &amp;lt;path_to_your_project_to_update&amp;gt; --extension &amp;lt;path_to_unzipped_cms_extension&amp;gt; --target-tfm-support LTS --ignore-unsupported-features&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Expectations&lt;/h2&gt;
&lt;p&gt;You should not expect an fully converted project after the conversion. But the tool should convert many &quot;standard&quot; things so you can concentrate on the code parts that are specific to your project. A good start after the conversion of the tool is to review the .csproj file and see what packages that are referenced there. If you open the project in Visual Studio and expand the node &#39;Dependencies&#39; under the project then Visual Stuido will display warnings for dependencies that are not compatible with net5. Then you need to review the packages one by one to figure out if there is a corresponding package that is net5 compatible. If there is then you update the dependency, if not then you can temporarly remove (for example outcomment in .csproj) the dependency. Then after all dependecies are resolvable you can compile the project to find the errors. Then there will likley be an iterative process of fixing errors and compiling. But hopefully since you have run the tool many of the &quot;standard&quot; errors you would have seen if you would not have run the tool is fixed and the remaining ones are specific to your project.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Happy upgrading!&lt;/p&gt;</id><updated>2022-01-20T10:47:33.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>A smarter output cache</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2019/11/a-smarter-output-cache/" /><id>&lt;p&gt;During Ascend I saw on Linus Ekstr&amp;ouml;ms whishlist for better CDN support that he would like to be able to get a list of all content items that are part of a pages rendered output. I then recalled that I had done something in a related area before, see &lt;a href=&quot;https://github.com/jbearfoot/HtmlCache&quot;&gt;Russian doll caching&lt;/a&gt;. So now when we had a hackday I decided to see if I could build something that would fulfil Linus wish. So I took some inspiration from my previous work and created a context&amp;nbsp;&lt;em&gt;ContentRenderingTrackerContext&amp;nbsp;&lt;/em&gt;that stores information about all content items that are used during rendering of a request. It also keeps track if something on the rendering is personalized (ContentArea or XHtmlString). I then intercepted some components in CMS like &lt;em&gt;PropertyRenderer&amp;nbsp;&lt;/em&gt;(used by PropertyFor) to collect data in the context. This component is available in project &lt;a href=&quot;https://github.com/jbearfoot/ContentRenderingTracker/tree/master/ContentRenderingTracker&quot;&gt;ContentRenderingTracker.&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Smarter output cache&lt;/h2&gt;
&lt;p&gt;Then to test my tracker component I decided to create a&amp;nbsp;&lt;em&gt;ContentAwareOutputCacheAttribute.&amp;nbsp;&lt;/em&gt;It works a bit as the built-in attribute &lt;em&gt;ContentOutputCacheAttribute&amp;nbsp;&lt;/em&gt;but it is a little smarter. So for example when a content item is changed will it only invalidates the output cache for those pages that actually has used the changed content item, compared to the built-in who invalidates the output cache for all pages (since it does not know where the content item is used). The new attribute also uses the knowledge about usage of personalized content from the context and will not output cache pages that has personalized content (meaning the attribute can be used on all controllers and it will take care of if it should output cache or not due to personalized content usage). The attribute is available in project &lt;a href=&quot;https://github.com/jbearfoot/ContentRenderingTracker/tree/master/ContentAwareOutputCache&quot;&gt;ContentAwareOutputCache&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Output cache in Redis&lt;/h2&gt;
&lt;p&gt;The output cache attribute worked nice but it still requires that the page is rendered once (on that specific instance) before it gets output cached. I therefore decided to write a mvc filter that works in a similar way as the&amp;nbsp;&lt;em&gt;ContentAwareOutputCacheAttribute&lt;/em&gt; but with the difference that it caches the rendered page in Redis instead. The nice thing with this is that it also adresses the cold-start scenario (for example when a new instance of the web application is spun up due to scaling out). In that case can a new empty instance directly utilize the output cache without the need to do an initial rendering. That implementation is available in project &lt;a href=&quot;https://github.com/jbearfoot/ContentRenderingTracker/tree/master/RedisOutputCache&quot;&gt;RedisOutputCache&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I also added two versions of alloy, one that uses the attribute and one that uses the Redis caching. All code is available in repository &lt;a href=&quot;https://github.com/jbearfoot/ContentRenderingTracker&quot;&gt;ContentRenderingTracker.&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;&lt;span&gt;Disclaimer&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;span&gt;T&lt;/span&gt;&lt;span&gt;his is nothing offically supported by EPiServer, you are free to use it as you like at your own risk.&lt;/span&gt;&lt;/p&gt;</id><updated>2019-11-07T20:22:14.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Disable Visitor Group personalization</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2018/6/disable-visitor-group-personalization/" /><id>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;In EPiServer.CMS.Core.11.8.0 we released a feature (that is somewhat related to GDPR) which is the ability to turn of Visitor Group Personalization for all/some requests. We have not changed the default behavior which is that Visitor Group personalization is enabled but made it possible to control it by registering a component implementing IPersonalizationEvaluator in IOC container. The interface has a single method and looks like:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;/// &amp;lt;summary&amp;gt;
    /// Signature for a component that determine if personalization should be performed or not for the current request
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;remarks&amp;gt;
    /// Registration of an implementation is done by register the implemenation in IOC container
    /// &amp;lt;/remarks&amp;gt;
    public interface IPersonalizationEvaluator
    {
        /// &amp;lt;summary&amp;gt;
        /// Determines if current request should be personalized or not
        /// &amp;lt;/summary&amp;gt;
        bool Personalize();
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is an builtin implementation for &quot;Do Not Track&quot; header that can be registered. One thing to be aware of for custom implementations is that the implementation is likely to be called once for all request (we cache the request so it is only done once for each request) so any implementation should preferably be fast since it will affect the time on all requests.&lt;/p&gt;
&lt;p&gt;Read more at &lt;a href=&quot;/link/220cccce746a4e7b962f0593e0f259e2.aspx&quot;&gt;Disable visitor group personalization&lt;/a&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</id><updated>2018-06-01T13:22:44.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>IContentSaveValidate - validation with context</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2018/5/icontentsavevalidate/" /><id>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;This time I thought I should share a tip about a component IContentSaveValidate&amp;lt;TContent&amp;gt; that we added a while ago but that perhaps not all are aware of.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;In&amp;nbsp;CMS 7 we added the&amp;nbsp;EPiServer.Validation.IValidate&amp;lt;T&amp;gt; interface, which has a signature like:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt; /// &amp;lt;summary&amp;gt;
    /// Defines the signature for a component that validates instances of &amp;lt;typeparamref name=&quot;T&quot;/&amp;gt;.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;typeparam name=&quot;T&quot;&amp;gt;&amp;lt;/typeparam&amp;gt;
    public interface IValidate&amp;lt;T&amp;gt; : IValidate
    {
        /// &amp;lt;summary&amp;gt;
        /// Validates the specified instance.
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name=&quot;instance&quot;&amp;gt;The instance.&amp;lt;/param&amp;gt;
        /// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
        IEnumerable&amp;lt;ValidationError&amp;gt; Validate(T instance);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The idea with the interface was to make it possible to extend the validation possibilities offered by validation attributes. So when calling IValidationService.Validate for an item then will the service first locate all registered validators that&amp;nbsp;has a generic type parameter T which the item can be assigned to and then call validate on them. So&amp;nbsp;say for example that we are validating an instance of StandardPage then would validators implementing IValidate&amp;lt;StandardPage&amp;gt;, IValidate&amp;lt;PageData&amp;gt; and IValidate&amp;lt;IContent&amp;gt; be called but not a validator implementing IValidate&amp;lt;IContentMedia&amp;gt;.&lt;/p&gt;
&lt;p&gt;The IValidate&amp;lt;T&amp;gt; interface does not have any type constraint but it is most commonly used during save of content instances. However there&amp;nbsp;might be cases where you want to do the validation only for certain state transitions, for example when the content is published. With IValidate&amp;lt;T&amp;gt; it is not possible to distinguish which state transition it is (if any). Therefore we introduced the more specialized interface IContentSaveValidate&amp;lt;TContent&amp;gt; that looks like:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public interface IContentSaveValidate&amp;lt;TContent&amp;gt; : IContextValidate&amp;lt;TContent, ContentSaveValidationContext&amp;gt;
        where TContent : IContentData
    {
        /// &amp;lt;summary&amp;gt;
        /// Validates the specified instance given specified context
        /// &amp;lt;/summary&amp;gt;
        /// &amp;lt;param name=&quot;instance&quot;&amp;gt;The instance that is validate&amp;lt;/param&amp;gt;
        /// &amp;lt;param name=&quot;context&quot;&amp;gt;The context for the validation&amp;lt;/param&amp;gt;
        /// &amp;lt;returns&amp;gt;A list of validation errors or empty list if instance is valid&amp;lt;/returns&amp;gt;
        IEnumerable&amp;lt;ValidationError&amp;gt; Validate(TContent instance, ContentSaveValidationContext context);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;Now in addition to the content item to validate you also get a context where you can get the state transtion from. Below is an example of an implementation that only validates when a StandardPage is published.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;    [ServiceConfiguration(IncludeServiceAccessor = false)]
    public class StandarPagePublishedValidator : IContentSaveValidate&amp;lt;StandardPage&amp;gt;
    {
        private readonly IStatusTransitionEvaluator _statusTransitionEvaluator;

        public StandarPagePublishedValidator(IStatusTransitionEvaluator statusTransitionEvaluator)
        {
            _statusTransitionEvaluator = statusTransitionEvaluator;
        }

        public IEnumerable&amp;lt;ValidationError&amp;gt; Validate(StandardPage instance, ContentSaveValidationContext context)
        {
            var transition = _statusTransitionEvaluator.Evaluate(instance, context.SaveAction);
            if (transition.NextStatus == VersionStatus.Published)
            {
                //do validation for publish here
            }
            return Enumerable.Empty&amp;lt;ValidationError&amp;gt;();
        }
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</id><updated>2018-05-22T14:58:57.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>IObjectInstanceCache.ReadThrough</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2018/5/iobjectinstancecache-readthrough/" /><id>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;I thought I should&amp;nbsp;share a small tip about a feature that we use internally but that perhaps not all are aware of that it exists. It is probably nothing you will use everyday but it can be really handy if you have &quot;expensive&quot; outbound calls to e.g. the database or a Web API. That is the extension method &lt;a href=&quot;/link/55fe410f4f65482cab72fb59d47c7561.aspx?documentId=cms/10/A030FFCA&quot;&gt;ReadThrough &lt;/a&gt;on interface IObjectInstanceCache.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The signature look like (there are some overloads for example to specify CacheEvictionPolicy)&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;public static T ReadThrough&amp;lt;T&amp;gt;(
	this IObjectInstanceCache cache,
	string key,
	Func&amp;lt;T&amp;gt; readValue,
	ReadStrategy readStrategy
)
where T : class&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The generic type parameter T is the expected type of the item to read/cache. The parameter key is the cachekey for the item. readValue parameter is a delegate that will be called to load the item (and putting it in cache) when it does not exist in cache. Now the interesting parameter here is the readStrategy. That is an enum that can have two values &lt;em&gt;Immediate&amp;nbsp;&lt;/em&gt;which will call the readValue delegate immediately to load the item in case it is not present in cache. The other readStrategy option is &lt;em&gt;Wait.&amp;nbsp;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A strategy &lt;em&gt;Wait&lt;/em&gt; means that when the first request comes in and find that the item queried for is not present in cache then it will put a marker in cache and then call the readValue delegate to load the item. Now if a second request comes in and asks for the same item before the first readValue delegate has finished then the cache will notice that there is a marker for that item (meaning it is being loaded) and then the readValue delegate will &lt;strong&gt;not&lt;/strong&gt; be called for the second request. Instead will it be put to wait for the first request to finish and then it gets the result from the first request.&lt;/p&gt;
&lt;p&gt;So by using Wait strategy you can avoid that several threads simultaneously makes the same expensive call. Instead one call is made and the result is then shared. So if you have some&amp;nbsp;code where you expect that several parallell request might hit at the same time then this could be useful. A typical such location could be resources loaded from startpage, menus etc that could be hit &lt;span&gt;simultaneously by several threads when site is restarted (and hence the cache is empty).&lt;/span&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</id><updated>2018-05-11T08:40:58.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Extended routing for Episerver Content Delivery API</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2018/5/extended-routing-for-episerver-content-delivery-api/" /><id>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;Episerver Content Delivery API delivers content through Urls like:&amp;nbsp;&lt;a href=&quot;http://&amp;lt;your-site-url&amp;gt;/api/episerver/v1.0/site/&quot;&gt;http://&amp;lt;your-site-url&amp;gt;/api/episerver/v1.0/content/&lt;/a&gt;&amp;lt;contentReference&amp;gt;. During my hackday I thought I should extend the CMS routing so that it is possible to use the same &quot;Friendly URLs&quot; as in CMS. My idea was to hook into the CMS routing and after a content has been routed look at the &lt;em&gt;Accept&lt;/em&gt; header and in case it was &quot;application/json&quot; rewrite the request to the Web API controller in EPiServer Content Delivery.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So I did not want to do any Json serialization but rely on Content Delivery API for that (same with access checks) and I did not want todo a redirect but stay on the friendly url.&lt;/p&gt;
&lt;p&gt;It turned out to work quite straightforward. I found a small issue in CMS (which I reported an bug for) that made it a bit&amp;nbsp;more&amp;nbsp;complicated than it should have needed to be, but it was quite easy to workaround.&lt;/p&gt;
&lt;p&gt;The result looks like this for an alloy site when applying Accept header:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/fe0ac111694349838473e8be4af16c5a.aspx&quot; width=&quot;1034&quot; alt=&quot;Image Content_Json.PNG&quot; height=&quot;309&quot; /&gt;&lt;/p&gt;
&lt;p&gt;One thing that often is a problem with REST is that you often gets huge Json responses even if you are only interested in some property. A nice solution to that problem is Graph QL, for this hackday though I did not have time to look into adding Graph QL support (perhaps a topic for next hackday). What I did instead was adding a partial router that routes to individual properties for content and then I added an action filter to the WebAPI where I filter the Json result to the routed property. So then it is possible to do requests for individual properties like below where &lt;em&gt;Name&lt;/em&gt; and &lt;em&gt;MainContentArea &lt;/em&gt;are properties on the content item with url http://localhost:63139/en/alloy-track:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/7f82e08d4d204f63b0aa24ba4253c4f1.aspx&quot; width=&quot;354&quot; alt=&quot;Image NameJson.PNG&quot; height=&quot;149&quot; /&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/2c83188b5e3546e2a23974022c5d519d.aspx&quot; width=&quot;973&quot; alt=&quot;Image PropertyJson.PNG&quot; height=&quot;247&quot; /&gt;&lt;/p&gt;
&lt;p&gt;The code is available at&amp;nbsp;&lt;a href=&quot;https://github.com/jbearfoot/ContentDeliveryExtendedRouting&quot;&gt;https://github.com/jbearfoot/ContentDeliveryExtendedRouting&lt;/a&gt;&amp;nbsp;(there is also a nuget package there that you can install). The module does not need any configuration or setup of either CMS or ContentDelivery its just reference it and it should just work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is nothing offically supported by EPiServer, you are free to use it as you like at your own risk.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</id><updated>2018-05-03T13:09:33.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Russian doll caching - lightning fast rendering</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2017/12/html-caching-in-redis/" /><id>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;I spent a hackday with looking at implementing a russian doll based html cache&amp;nbsp;for CMS. I think the result was so interesting so I thought I should share it. I will describe russian doll caching more later but in short the idea is to cache chunks of already rendered html. It is a fairly long post but I hope you will find it worth reading, it offers a huge performance boost!&lt;/p&gt;
&lt;p&gt;A&amp;nbsp;specific usecase I had in mind was large sites where the rendering is dependent on a lot of content items. One such example could be a commerce site where the start page could contain several product listings and menus which require a lot of content items to be rendered. Such sites is very dependent on the content cache to perform well. That means that when a new instance of the application is started (for example due to autoscale in Azure) it must first load up alot of content items in cache before it perform well.&lt;/p&gt;
&lt;h2&gt;Russian Doll caching&lt;/h2&gt;
&lt;p&gt;The idea with russian doll caching is to cache items in several layers where each layer has a dependency on next layer, it is used for example in&amp;nbsp;&lt;a href=&quot;http://edgeguides.rubyonrails.org/caching_with_rails.html#russian-doll-caching&quot;&gt;Ruby on Rails&lt;/a&gt;. As an example we can look at the Content area rendered in picture below. The output of the content area as a whole will be cached at layer 1. The output of each item in the content area will then be cached at layer 2 and then individual properties for a content item will be cached in layer 3.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/link/d9c091f54a3746d393654eb645a9508b.aspx&quot; width=&quot;792&quot; alt=&quot;Image HtmlLayers.png&quot; height=&quot;660&quot; /&gt;&lt;/p&gt;
&lt;p&gt;There will be quite alot of redundance with meaning a specific html element might be cached several times in different layers however there are some good benefits with this. The first is that since layers are dependent on next layer then cache evictions can be propagated quite nicely. If we take the content area as an example then if a content item in an area is changed then the html for that specific item is evicted and then that is propagated to next layer meaning the html for the content area as a whole is evicted as well. The next nice thing with this caching teqnique is if we take the content area again as example. When one item is changed the output for that item and the content area as whole gets evicted however the output for all other items in the content area are still valid. That means that the next time the area is to be rendered it only needs to render that specific item and then put together that output with the other already cached items to render the area as whole.&lt;/p&gt;
&lt;h2&gt;Distributed cache&lt;/h2&gt;
&lt;p&gt;Altough it is possible to use this caching technique with an in-process cache I think it is much better suited for an out of process distributed cache. One reason is that the caching will likely&amp;nbsp;contain quite alot of large html strings that will fill up the memory but also for the usecase above. In that case when a new instance of the site is spinned up it can serve html chuncks fetched from cache without having to fill up the object cache with alot of content items. Probably those large sites could run with much less RAM as well due to that.&lt;/p&gt;
&lt;p&gt;So I have looked at Redis for this. One common way to use Redis is to use it as a distributed object cache. The usecase above could probably be helped with a distributed content cache. In my case I&amp;nbsp;however use Redis as a cache for Html. Then the cost for serializing/deserializing can be avoided and it also makes it possible to cache at a much higher level than with a distributed object cache.&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;IHtmlCache&lt;/h2&gt;
&lt;p&gt;I have created an interface IHtmlCache that can be used to get/add html to the cache. The interface is registered in the IOC container. The interface has a single method like:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;string GetOrAdd(string key, Func&amp;lt;IRenderingContext, string&amp;gt; renderingCallback);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;span&gt;The way to use the method is to first create a cache key that should be unique for the context (colud be built from e.g. current content, current property and current template). Then a call is maid against the method GetOrAdd. If the item is already cached you get the html result back otherwise the renderingCallback Func is called where you specify how to render the html. Then the result is cached and returned. The argument &lt;em&gt;IRenderingContext&amp;nbsp;&lt;/em&gt;that gets passed to the callback makes it possible to for example add content dependencies. The current &lt;em&gt;IRenderingContext&amp;nbsp;&lt;/em&gt;can also be retrieved from IOC container using &lt;em&gt;IRenderingContextResolver.&amp;nbsp;&lt;/em&gt;This can be useful if you have for example a listing block that is dependent on some listing, then you can add a dependecy to that listing in for example the block controller (see&amp;nbsp;PageListBlockController in my Alloy project).&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;PropertyFor and Content rendering&lt;/h2&gt;
&lt;p&gt;To inject the html cache in the CMS rendering I choosed to intercept &lt;em&gt;PropertyRenderer,&lt;/em&gt; &lt;em&gt;ContentAreaRenderer&lt;/em&gt; and &lt;em&gt;IContentRenderer.&amp;nbsp;&lt;/em&gt;The interceptors basically checks if the&amp;nbsp;html output for the item&amp;nbsp;to be rendered is already cached. If so the html is returned else the default renderer is called and the output is captured and cached. During the rendering it also creates dependencies to the content item(s) that the output is dependent on. That is so the right html elements gets evicted for example when a content item is published.&lt;/p&gt;
&lt;h2&gt;Personalization&lt;/h2&gt;
&lt;p&gt;This caching technique is somewhat related to output cache, but in that case is the whole html for a page cached as whole. One problem is that is hard to know which content item that affected the rendering and hence is the whole output cache evicted (for all pages) when some content is published. Also output cache is hard to use with personalization since it is all or nothing that gets cached. With russian doll caching it was possible to handle personalization much nicer. Say for example that a page contains a content area or a xhtmlstring that is personalized. Then we can avoid to cache that specific property but still cache the html for other items on that page such as menus, listings and other contentareas or xhtmlstrings.&lt;/p&gt;
&lt;h2&gt;Alloy modifications&lt;/h2&gt;
&lt;p&gt;I have uploaded a somewhat modified Alloy site together with the code for the html cache to my &lt;a href=&quot;https://github.com/jbearfoot/HtmlCache&quot;&gt;git hub repository&lt;/a&gt;. I have added a Block type NowBlock which can be used to verify that personalization of ContentArea and XhtmlString works as expected. I have also added an action filter that writes out the rendering time for request in the bottom left of the page. There are also a noop and an in-process implemenation of IDistributedCache that can be registered by selecting which &lt;em&gt;IDistributedCache &lt;/em&gt;implementation that is registered&amp;nbsp;in Alloy/HtmlCache/DistributedCacheConfigurationModule.cs. That can be used to compare the rendering time for inprocess-cache, redis cache and no html cache (it still uses the content cache in this case).&lt;/p&gt;
&lt;h3&gt;Menu&lt;/h3&gt;
&lt;p&gt;I have changed the Menu in Alloy/Helpers/HtmlHelpers.cs so it uses the html cache. You can see in the code that it also caches at several layers, first the menu as whole but also individual menu items. Meaning if one item would be evicted then that item and the menu as whole needs to get re-rendered but the html output from all other items remains and can be reused to render the menu as whole.&lt;/p&gt;
&lt;h3&gt;Footer&lt;/h3&gt;
&lt;p&gt;On Alloy all pages uses the same footer that has some page listings. However&amp;nbsp;those page listing is&amp;nbsp;not dependent on the current rendered page, instead those are defined on start page. Therefore has the PropertyFor calls in Footer.cshtml been modified to the pass in which content it is dependent on(the default behaviour is current rendered content).&lt;/p&gt;
&lt;h2&gt;Async&lt;/h2&gt;
&lt;p&gt;Since calls to Redis is out of process calls I initially thought it would make sense to use the async overloads of the methods. However my impression was that the sync calls where much more stable and also since the MVC 5&amp;nbsp;APIs I interact with is synchronus I choosed the sync methods. However my impression is that Redis is lightning fast so I have not seen any problems with it. But if this where to be implemented for ASP.NET Core I would probably look at the async alternatives again.&lt;/p&gt;
&lt;h2&gt;Performance&lt;/h2&gt;
&lt;p&gt;I measure the rendering tims by adding an action filter (defined in Alloy/HtmlCache/RenderTimeFilter.cs), it starts a stopwatch in OnActionExecuting and stops it at OnResultExecuted. So the measurement is the time for serverside rendering (it does not include the time for network transfer). The actual figures are not that interesting since it dependens on your machine etc, but the comparsion between the different options are insteresting. Also running Alloy locally on the machine is fast anyway so it can be hard to see/feel the difference.&lt;/p&gt;
&lt;p&gt;When&amp;nbsp;comparing the results for page &quot;About us&quot; that does not have any personalizaton, but a top and left menu and some listings in footer and some content properties.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;No html cache ~20-25 ms&lt;/p&gt;
&lt;p&gt;Redis ~ 5-8 ms&lt;/p&gt;
&lt;p&gt;In-Memory 3-5 ms&lt;/p&gt;
&lt;p&gt;When testing on News&amp;amp;Events which has a PageListBlock instance that prevents caching I get result as:&lt;/p&gt;
&lt;p&gt;No Html cache ~25-30ms&lt;/p&gt;
&lt;p&gt;Redis ~15-18 ms&lt;/p&gt;
&lt;p&gt;In-memory ~12-15 ms&lt;/p&gt;
&lt;p&gt;In this case the page list block prevents caching of the content area. Also the page list block is rendered through a partial controller so the effect is not as significant for this page (the same applies for pages Alloy Plan, Alloy Track and Alloy Meet which all has PageListBlock instances).&lt;/p&gt;
&lt;p&gt;So the result is that when no personalization is used the improvment is massive! And when there is personalization we&amp;nbsp;also see a significant improvment even though it is not equally impressive&amp;nbsp;(especially when the non cached item is a block rendered through a partial controller). Another thing to notice is that using Redis as a distributed cache is not that much less performant than an in-memory cache.&lt;/p&gt;
&lt;h2&gt;Thougths&lt;/h2&gt;
&lt;p&gt;In my implementation I went &quot;All-In&quot; meaning it caches a whole lot for example the output all properties. It would be possible to adjust it to just cache some specific property types (e.g. ContentArea and XhtmlString) or to avoid caching property output at all. A suggestion could be to profile the application to see what gives most benefit (menus and listings are good candidates) and start with that. Especially if you cache in-process you might want to limit what to cache. However I strongly suggest a distributed cache, that&amp;nbsp;also addresses the cold start scenario.&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Give it a spin&lt;/h2&gt;
&lt;p&gt;The code can be cloned from&amp;nbsp;&lt;span&gt;my&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://github.com/jbearfoot/HtmlCache&quot;&gt;git hub repository&lt;/a&gt;. It includes an Alloy site that you can run to test the code on, should be just to press F5. I have not tested it on any larger site but as I see it those sites should be the ones that has most benefit of this (especially if you use the distributed cache). To run the Redis implementation you need to install Redis locally or on some other machine. You could create it in Azure as well but that is probably a bit unfair (when you compare with e.g. in-process) unless you deploy the application to Azure as well.&lt;/p&gt;
&lt;h2&gt;Disclamiers&lt;/h2&gt;
&lt;p&gt;This is nothing offically supported by EPiServer, you are free to use it as you like at your own risk.&lt;/p&gt;
&lt;p&gt;It is currently not in production quality, for example are there no tests or fault handling.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</id><updated>2017-12-14T20:44:53.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>EPiServer.ServiceLocation.StructureMap 2</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2017/11/episerver-servicelocation-structuremap-2/" /><id>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;We have now released version 2 of EPiServer.ServiceLocation.StructureMap. This version has a dependency against version 4.5.2 of the unsigned version of StructureMap. According to &lt;a href=&quot;http://structuremap.github.io/release-notes/&quot;&gt;release notes&lt;/a&gt; in StructureMap documentation the newer version contains (among other things) performance improvments.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;There are some nuget issues that could be good to know about when updating EPiServer.ServiceLocation.StructureMap. Nuget will not remove references to the packages&amp;nbsp; &lt;em&gt;structuremap-signed&lt;/em&gt; and &lt;em&gt;structuremap.web-signed&lt;/em&gt; used by version 1 of EPiServer.ServiceLocation.StructureMap during update. So a recommendation after updating is to uninstall those packages. Also any existing binding redirects to the signed version of StructureMap assembly&amp;nbsp;will remain in web.config.&lt;/p&gt;
&lt;p&gt;An alternative to update package is to first uninstall package EPiServer.ServiceLocation.StructureMap, make sure to select option &quot;Remove dependencies&quot;. If you have an dependency to package EPiServer.CMS you must also select option &quot;Force uninstall&quot;. Then install version 2 of package EPiServer.ServiceLocation.StructureMap. Even in this case there might be old binding redirects left in web.config.&lt;/p&gt;
&lt;p&gt;The package has been tested with CMS and we are currently testing it with other products such as Commerce and Find, to make sure it is compatible with other products as well.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</id><updated>2017-12-04T11:36:45.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>CMS 11 - A package breaking release </title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2017/11/cms-11-and--net-standard-compliance/" /><id>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;p&gt;&lt;span&gt;At Episerver we are using continuous releases and&amp;nbsp;we follow&amp;nbsp;&lt;a href=&quot;https://semver.org/&quot;&gt;semantic versioning&lt;/a&gt;. That means that we release features and bugfixes continuously. A major release indicates that there is breaking change compared to the previous version. The main breaking change we have introduced in CMS 11 is that we have separated our packages in &quot;core&quot; runtime packages and packages dependent on specific technologies. Some of the new packages are:&lt;/span&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;EPiServer.Framework.AspNet&lt;/strong&gt;,&amp;nbsp;&lt;strong&gt;EPiServer.CMS.AspNet&amp;nbsp;&lt;/strong&gt;- Contains the ASP.NET specific implementations of CMS like WebForms and MVC 5 support.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;EPiServer.ServiceLocation.StructureMap&amp;nbsp;&lt;/strong&gt;- A StructureMap based IOC implementation. Having this as a separate package opens up for newer version of unsigned StructureMap (planned to be release in a near future) but also for other implementations of IOC containers.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;EPiServer.XForms&lt;/strong&gt; - Optional package that can be used if xforms is used.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;EPiServer.DynamicContent&amp;nbsp;&lt;/strong&gt;- Optional package that can be used if dynamic content is used&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;EPiServer.Search.Cms&amp;nbsp;&lt;/strong&gt;- Optional package if EPiServer Search is used.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main purpose is to achieve a better separation of concern. One goal was to have a core runtime that is not dependent to be executed in a specific environment like&amp;nbsp;ASP.NET but instead can be setup in for example an integration test.&lt;/p&gt;
&lt;h2&gt;.NET Standard&lt;/h2&gt;
&lt;p&gt;&lt;span&gt;The&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://docs.microsoft.com/en-us/dotnet/standard/net-standard&quot; data-linktype=&quot;external&quot;&gt;.NET Standard&lt;/a&gt;&lt;span&gt;&amp;nbsp;is a formal specification of .NET APIs that are intended to be available on all .NET implementations.&amp;nbsp;The specification is maintained by .NET implementors, specifically Microsoft (includes .NET Framework, .NET Core and Mono) and Unity. The idea is that a library that is compliant with NET standard can be consumed and&amp;nbsp;executed on all environments where .NET is supported (a.k.a. cross-platform library).&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Previous to CMS 11 all Episerver CMS packages (e.g. EPiServer.Framework, EPiServer.CMS.Core) where dependent on assemblies only available on .NET Framework and could hence only execute on environments where .NET Framework is installed. &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;In CMS 11 our &quot;core&quot; packages EPiServer.Framework and EPiServer.CMS.Core are now .NET Standard 2.0 compliant. The packages EPiServer.Framework.AspNet and EPiServer.CMS.AspNet that contain the ASP.NET specific implementation&amp;nbsp;&lt;/span&gt;&lt;span&gt;(e.g. with dependecies to System.Web, System.Web.Mvc and System.Configuration) still requires .NET Framework.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;An overview of the packages are shown below:&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;img src=&quot;/link/29130338691f4ecc90e1bbd46df02f28.aspx&quot; width=&quot;736&quot; alt=&quot;Image CMS11.png&quot; height=&quot;414&quot; /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;The existing applications today&amp;nbsp;that are&amp;nbsp;ASP.NET application will require the EPiServer.CMS.AspNet package (supporting both WebForms and MVC 5)&amp;nbsp;and will execute on ASP.NET on .NET Framework.&amp;nbsp;However the separation of packages also opens up for example for integration tests (that do not require ASP.NET) and also since core packages are now .NET Standard compliant it is also possible to build other types of applications (e.g. Console application or Web API) based on .Net Core.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;We aim to release a package that will assist with setting up CMS runtime in an ASP.NET Core application within a near future. This package will for example contain an implementation of our IOC abstraction based on the default dependency injection implementation in .Net Core.&amp;nbsp;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</id><updated>2017-11-22T14:23:28.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Export/Import improvements</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2016/11/exportimport-improvments/" /><id>&lt;p&gt;There have been some improvements done regarding Import/Export functionality in CMS 10.2.0. Since Copy is based on same functionality as Export/Import features like point 3 below will affect Copy as well.&lt;/p&gt;
&lt;p&gt;Here is a summarized list of improvements:&lt;/p&gt;
&lt;p&gt;1. Possible to select other source/destination than pages during export/import. Meaning it is for example possible to export/import parts of the asset structure.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Image Export.png&quot; src=&quot;/link/9e97a907634245268d231f73cc6c76e0.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;2. Possible to specify if export should include descendents or just take a single content item.&lt;/p&gt;
&lt;p&gt;3. Better handling of &quot;duplicate&quot; content. For folders, it means no dupliate folders are created -&amp;nbsp;instead content items are merged into the existing folder. For other items (like pages, media, blocks) the name will be unique. So for example if there already exists a page or block (at same location and language) named &quot;News,&quot; then the imported will be named &quot;News(2)&quot; and for media it would be for example &quot;SomeMedia(2).png&quot;.&lt;/p&gt;
&lt;p&gt;4. Possible to specify to import a single language branch. Export will always include all language versions for content items. However during import it is possible to select to import a single language branch.&lt;/p&gt;
&lt;p&gt;A bonus feature is a new admin tool &quot;Manage Content&quot;&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Image ManageContent.png&quot; src=&quot;/link/4b817f7ac40a43dea05f01c6cc330e7a.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;One use case is if the site uses custom content types (IContent implementations) since the edit UI by default only shows &quot;known&quot; types (like pages, media, blocks) there is no way to delete custom content items from the UI. The &quot;Manage Content&quot; tool will show custom content types as well, and hence make it possible to delete them.&lt;/p&gt;
&lt;p&gt;Another use case:&amp;nbsp;since export/import now can be done across the content structure,&amp;nbsp;there may be cases where an import &quot;goes wrong&quot; meaning the content ends up in the wrong structure. There is validation that items should be imported in same &quot;known&quot; structure (for example is it not possible to export from page structure and import into asset structure.) But since the system&amp;nbsp;has no&amp;nbsp;knowledge about all custom types and custom structures, the validation might fail.&amp;nbsp;In that case, the &quot;Manage Content&quot; tool can be handy.&lt;/p&gt;</id><updated>2016-12-05T20:19:28.8330000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Internationalized Resource Identifiers (IRIs)</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2016/9/international-resource-identifier-iri-support/" /><id>&lt;p&gt;An Internationalized Resource Identifier (IRI) is a network address that contain non ASCII&amp;nbsp;characters as below:&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Image IRI.png&quot; src=&quot;/link/8c5184c2a345494693d4eb1965579599.aspx&quot; /&gt;&lt;/p&gt;
&lt;p&gt;EPiServer CMS has previously (prior to 10) only allowed characters in url segments&amp;nbsp;according to &lt;a href=&quot;http://www.faqs.org/rfcs/rfc1738.html&quot;&gt;RFC 1738&lt;/a&gt;&amp;nbsp;which basically allows&amp;nbsp;ALPHA / DIGIT / &#39;-&#39;/ &#39;_&#39;/ &#39;~&#39; / &#39;.&#39;/ &#39;$&#39;/.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;It is now (from CMS.Core version 10.1.0) however possible to define a custom character set that are used for url segments and simple address. This is done by registering an instance of &lt;em&gt;UrlSegmentOptions&lt;/em&gt;&amp;nbsp;with a custom regular expression in IOC container. When an expression is set that allows characters outside RFC 1738 the setting &lt;em&gt;UrlSegementOptions.Encode&lt;/em&gt;&amp;nbsp;is recommended to be set to true so that url:s gets properly encoded. Below is an example of how a character set that allows unicode characters in the letter category.&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;using EPiServer.ServiceLocation;
using EPiServer.Framework.Initialization;
using EPiServer.Framework;
using EPiServer.Web;

namespace EPiServerSite6
{
    [ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
    public class IRIConfigurationModule : IConfigurableModule
    {
        public void ConfigureContainer(ServiceConfigurationContext context)
        {
            context.Services.RemoveAll&amp;lt;UrlSegmentOptions&amp;gt;();
            context.Services.AddSingleton&amp;lt;UrlSegmentOptions&amp;gt;(s =&amp;gt; new UrlSegmentOptions
            {
                Encode = true,
                ValidUrlCharacters = @&quot;\p{L}0-9\-_~\.\$&quot;
            });
        }

        public void Initialize(InitializationEngine context)
        {}

        public void Uninitialize(InitializationEngine context)
        {}
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;UrlSegmentOptions &lt;/em&gt;also exposes a &lt;em&gt;CharacterMap &lt;/em&gt;property where it is&amp;nbsp;possible to define a mapping for unsupported characters, for example &#39;&#246;&#39; =&amp;gt; &#39;o&#39;.&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;Internationalized Domain Names (IDN)&lt;/h2&gt;
&lt;p&gt;As explained in &lt;a href=&quot;https://www.w3.org/International/articles/idn-and-iri/&quot;&gt;IDN and IRI&lt;/a&gt;&amp;nbsp;are internationalized domain names registered in its punycode format&amp;nbsp;(a way of representing Unicode characters using only ASCII characters).&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Internationalized domain names should be registered in admin mode under &lt;em&gt;Manage Websites&lt;/em&gt; in their punycode format.&amp;nbsp;&lt;/p&gt;</id><updated>2016-11-15T14:59:39.2530000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Changes regarding language handling during content loading in CMS8</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2015/2/changes-regarding-language-handling-during-content-loading-in-cms8/" /><id>&lt;h2&gt;Background&lt;/h2&gt;
&lt;p&gt;Previously there were overloads to content loading methods in &lt;em&gt;IContentLoader&lt;/em&gt; that took an &lt;em&gt;ILanguageSelector&lt;/em&gt; as a parameter. When working on multilingual sites these overloads could be used to load content in a specific language, and/or define if language fallback rules should apply.&lt;/p&gt;
&lt;p&gt;The way it worked behind the scenes during load was that first the content provider could operate on the passed in language selector to decide which language to return. Then the language selector was used again to select which language version to return according to defined language fallback rules.&lt;/p&gt;
&lt;p&gt;The main implementation of &lt;em&gt;ILanguageSelector&lt;/em&gt; is &lt;em&gt;LanguageSelector&lt;/em&gt;. It is a fairly complex class that previously both acted as a data carrier as well as a service. It can be hard to handle in unit tests, mainly due to a static dependency to &lt;em&gt;ContentLanguage.PreferredCulture&lt;/em&gt; but also complexity to mock. Another feedback we heard was from implementers of content providers was that the language selector is complex to work with.&lt;/p&gt;
&lt;p&gt;We finally ran into some issue with the language selector and the Preview functionality in the recently introduced Project feature (&lt;a href=&quot;/link/18c5228d9fcb4922976c83db606c4ab0.aspx&quot;&gt;beta description of projects&lt;/a&gt;). As the language fallback functionality in the &lt;em&gt;LanguageSelector&lt;/em&gt; was run after the project version was selected it would not take projects into consideration and the two features would not work well together.&lt;/p&gt;
&lt;p&gt;So the current language handling using &lt;em&gt;LanguageSelector&lt;/em&gt; which already was complex did not work very well in the project preview scenario. We did not want to add project awareness to LanguageSelector, due to the tight coupling this would mean, also considering that LanguageSelector was already complex in its own.&lt;/p&gt;
&lt;h2&gt;New loading handling&lt;/h2&gt;
&lt;p&gt;So we decided to do some improvements regarding language handling during content loading. Some of the goals we set up where:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Possibility to specify options for language that does not have static dependencies such as ContentLanguage.PreferredCulture or the inversion of control magic (SelectPageLanguage etc)&lt;/li&gt;
&lt;li&gt;Make a smooth upgrade from CMS7, preferably just a recompile without changing any code&lt;/li&gt;
&lt;li&gt;Simplify language selector and how to use it&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We moved the language selection from the content provider level to the loader above the providers. We have changed &lt;em&gt;IContentLoader&lt;/em&gt; by replacing the ILanguageSelector with &lt;em&gt;LoaderOptions&lt;/em&gt; instead. We have also added simpler overloads that just take a CultureInfo. LoaderOptions is basically just a collection of LoaderOption (currently there are LanguageLoaderOption and ProjectLoaderOption). During loading there are specific components that acts on the different loader options, affecting which language/version of a content to return.&lt;/p&gt;
&lt;h2&gt;What about LanguageSelector?&lt;/h2&gt;
&lt;p&gt;To minimize the impact on existing code, we have changed LanguageSelector to inherit from LoaderOptions. This means you can still pass in a LanguageSelector to the overloads that take a LoaderOption. We have changed the implementation of LanguageSelector so that the constructor and the static methods (like MasterLanguage) creates corresponding LoaderOptions instances. This means there is no immediate demand to replace current usage of LanguageSelector as parameter to loading methods.&lt;/p&gt;
&lt;h2&gt;Usage of IContentLoader&lt;/h2&gt;
&lt;p&gt;Below are some examples on how to load content with some different fallback strategies applied. The examples shows usage of LanguageSelector and alternatives using CultureInfo and LoaderOptions instead.&lt;/p&gt;
&lt;h3&gt;Loading specific language&lt;/h3&gt;
&lt;p&gt;Loading a page in a specific language, using LanguageSelector:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;swedishPage = contentLoader.Get&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;StandardPage&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;&amp;gt;(contentLink, &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;LanguageSelector&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background: white; color: #a31515;&quot;&gt;&quot;sv&quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using the new overload that takes a CultureInfo, the same page can be loaded as:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;swedishPage = contentLoader.Get&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;StandardPage&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;&amp;gt;(contentLink, &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;CultureInfo&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.GetCultureInfo(&lt;/span&gt;&lt;span style=&quot;background: white; color: #a31515;&quot;&gt;&quot;sv&quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is equivalent to:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;swedishPage = contentLoader.Get&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;StandardPage&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;&amp;gt;(contentLink, 
    &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;LoaderOptions&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;(){ &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;LanguageLoaderOption&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.Specific(&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;CultureInfo&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.GetCultureInfo(&lt;/span&gt;&lt;span style=&quot;background: white; color: #a31515;&quot;&gt;&quot;sv&quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;)) });&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Loading master language&lt;/h3&gt;
&lt;p&gt;To load the master language version of a content (the master language version is the language version in which the common non-language specific properties are stored) using LanguageSelector:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;master = contentLoader.Get&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;StandardPage&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;&amp;gt;(contentLink, &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;LanguageSelector&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.MasterLanguage());&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Using the new overload that takes a CultureInfo the master version can be loaded as:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;master = contentLoader.Get&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;StandardPage&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;&amp;gt;(contentLink, &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;CultureInfo&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.InvariantCulture);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is equivalent to:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;master = contentLoader.Get&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;StandardPage&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;&amp;gt;(contentLink,
    &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;LoaderOptions&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;() { &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;LanguageLoaderOption&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.MasterLanguage() });&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Loading in current language with fallback&lt;/h3&gt;
&lt;p&gt;Using LanguageSelector to load a content instance in the same language as the current request was routed to:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;current = contentLoader.Get&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;StandardPage&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;&amp;gt;(contentLink, &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;LanguageSelector&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.AutoDetect());&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;LanguageSelector.AutoDetect() uses language fallback settings, which means that if the content does not exist in the requested language or if the language is not published, then another language version might be returned (according to defined fallback rules). Using LoaderOptions the call would look like:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;current = contentLoader.Get&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;StandardPage&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;&amp;gt;(contentLink, &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;LoaderOptions&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;() { &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;LanguageLoaderOption&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.Fallback() });&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Loading specific language with fallback (including master)&lt;/h3&gt;
&lt;p&gt;Loading content in a preferred culture with fallback rules applied, including a final fallback to master (if no other fallback rules apply) can be done using LanguageSelector:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;fallback = contentLoader.Get&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;StandardPage&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;&amp;gt;(contentLink, &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;LanguageSelector&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.Fallback(&lt;/span&gt;&lt;span style=&quot;background: white; color: #a31515;&quot;&gt;&quot;sv&quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;));&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The equivalent call using LoaderOptions is:&lt;/p&gt;
&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;fallback = contentLoader.Get&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;StandardPage&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;&amp;gt;(contentLink, &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;LoaderOptions&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;(){ &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;LanguageLoaderOption&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.FallbackWithMaster(&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af;&quot;&gt;CultureInfo&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.GetCultureInfo(&lt;/span&gt;&lt;span style=&quot;background: white; color: #a31515;&quot;&gt;&quot;sv&quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;)) });&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Related changes&lt;/h2&gt;
&lt;h3&gt;Changes in IContentRepository&lt;/h3&gt;
&lt;p&gt;The methods &lt;em&gt;CreateLanguageBranch&lt;/em&gt; and &lt;em&gt;GetDefault&lt;/em&gt; have been simplifed to take a CultureInfo as parameter, instead of an ILanguageSelector.&lt;/p&gt;
&lt;h3&gt;ILanguageSelector and content providers&lt;/h3&gt;
&lt;p&gt;The interface ILanguageSelector has been simplified to only contain a single property Language of type CultureInfo. This means content provider implementations no longer needs to call any methods on ILanguageSelector to decide which language version to return. Instead they can just return the language version specified by ILanguageSelector.Language. If CultureInfo.InvariantCulture is passed in, the provider should return content in the master language. If the content does not exist in the specified language, then the master language should be returned.&lt;/p&gt;
&lt;h3&gt;ContentReference.GetPublishedOrLatest&lt;/h3&gt;
&lt;p&gt;ContentReference has a property GetPublishedOrLatest that loads the published version or the latest version if no published version exists. When using this property with language fallback previously it only loaded published versions in the fallback chain. This has been corrected to select the published or latest version in the fallback chain as well. This property is normally not used in templates.&lt;/p&gt;
&lt;h3&gt;ILanguageSelectionSource&lt;/h3&gt;
&lt;p&gt;In previous versions of CMS, it was possible to cast the passed in LanguageSelector to ILanguageSelectionSource after content retrieval. That interface contained information about why the content was selected, for instance that the content was selected due to language fallback or replacement rules. The same information can now be retrieved after content retrieval by calling MatchLanguageSettings on IContentLanguageSettingsHandler passing in the retrieved content instance and the requested language.&lt;/p&gt;</id><updated>2015-02-20T09:51:32.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Changes in simple address routing</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2014/9/Changes-in-simple-address-routing/" /><id>&lt;p&gt;In package EPiServer.CMS.Core.7.13.3 we have solved an issue that causes a slightly different behaviour in how simple addresses are routed. As a background: for “ordinary” content routing we introduced a more strict handling in 7.5 where for example it was not possible to have a language segment specifying one language while the segment it self was on a content instance on another language. Like for example: &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://mysite/en/produkter&quot;&gt;http://mysite/en/produkter&lt;/a&gt; (where “produkter” is the segment on the swedish version)&lt;/p&gt;  &lt;p&gt;In CMS 7 that was possible to route and resulted in the english version of the page. In CMS 7.5 that results in a 404. We also introduced a configuration setting strictLanguageRouting that can be set to false to get the more tolerant behaviour as in CMS 7.&lt;/p&gt;  &lt;p&gt;Now we have also changed simple address routing so it is more strict. So given that a page exist in both language &amp;quot;en&amp;quot; and language &amp;quot;sv&amp;quot; and has simple addresses &amp;quot;ensimple&amp;quot; and &amp;quot;svsimple&amp;quot; the following scenarios apply. For those scenarios that differs from previous version a parenthesis is added describing the old behaviour:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;No host language mapping, strictLanguageRouting=true&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;     &lt;p&gt;http://sitehost/ensimple =&amp;gt; english page&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;http://sitehost/svsimple =&amp;gt; swedish page&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;http://sitehost/en/ensimple =&amp;gt; english page&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;http://sitehost/sv/svsimple =&amp;gt; swedish page&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;http://sitehost/sv/ensimple =&amp;gt; 404 (this gave swedish page in previous version)&lt;/p&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;No host language mapping, strictLanguageRouting=false&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;     &lt;p&gt;http://sitehost/ensimple =&amp;gt; english page&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;http://sitehost/svsimple =&amp;gt; swedish page&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;http://sitehost/en/ensimple =&amp;gt; english page&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;http://sitehost/sv/svsimple =&amp;gt; swedish page&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;http://sitehost/sv/ensimple =&amp;gt; swedish page&lt;/p&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;Host &amp;quot;sitehost&amp;quot; mapped to language &amp;quot;en&amp;quot;, strictLanguageRouting=true&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;     &lt;p&gt;http://sitehost/ensimple =&amp;gt; english page&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;http://sitehost/svsimple =&amp;gt; 404 (this gave english page in previous version)&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;http://sitehost/en/ensimple =&amp;gt; 404 (this gave english page in previous version)&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;http://sitehost/sv/svsimple =&amp;gt; swedish page&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;http://sitehost/sv/ensimple =&amp;gt; 404 (this gave swedish page in previous version)&lt;/p&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;&lt;strong&gt;Host &amp;quot;sitehost&amp;quot; mapped to language &amp;quot;en&amp;quot;, strictLanguageRouting=false&lt;/strong&gt;&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;     &lt;p&gt;http://sitehost/ensimple =&amp;gt; english page&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;http://sitehost/svsimple =&amp;gt; swedish page&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;http://sitehost/en/ensimple =&amp;gt; english page&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;http://sitehost/sv/svsimple =&amp;gt; swedish page&lt;/p&gt;   &lt;/li&gt;    &lt;li&gt;     &lt;p&gt;http://sitehost/sv/ensimple =&amp;gt; swedish page&lt;/p&gt;   &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;To get the more tolerant behaviour as in previous versions you can either set the strictLanguageRouting attribute (on configuration element applicationSettings) to false. That will however not only affect simple address but also &amp;quot;ordinary&amp;quot; routing so it works as in EPiServer 7. To only affect simple address you could have an initialization module that configures simple address routing to not use strict language routing as the following code:&lt;/p&gt;    &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;using &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;EPiServer.Framework;
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;using &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;EPiServer.Web.Routing;
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;using &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;System;
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;using &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;System.Collections.Generic;
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;using &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;System.Linq;
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;using &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;System.Web;

&lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;namespace &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;MvcPreview
{
    [&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;InitializableModule&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;]
    &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;public class &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;SimpleAddressModule &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;IInitializableModule
    &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;{
        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;public void &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;Initialize(EPiServer.Framework.Initialization.&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;InitializationEngine &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;context)
        {
            EPiServer.&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;Global&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.RoutesRegistered += &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;delegate&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;object &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;source, &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;RouteRegistrationEventArgs &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;args)
            {
                &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;simpleAddressRoute = args.Routes.OfType&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;ContentRoute&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;&amp;gt;().FirstOrDefault(r =&amp;gt; r.Name.Equals(&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(163, 21, 21);&quot;&gt;&amp;quot;simpleaddress&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;));
                &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;(simpleAddressRoute != &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;)
                {
                    simpleAddressRoute.StrictLanguageRoutingResolver = () =&amp;gt; &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;;
                }
            };
        }

        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;public void &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;Preload(&lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;[] parameters)
        {
        }

        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;public void &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;Uninitialize(EPiServer.Framework.Initialization.&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;InitializationEngine &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;context)
        {
        }
    }
}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</id><updated>2014-09-08T15:32:57.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>LocalMediaProvider</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2014/8/LocalMediaProvider/" /><id>&lt;p&gt;In the nuget package EPiServer.CMS.Core.7.13.0 is a new service IdentityMappingService introduced. The purpose of the service is to support external integrations (like a content provider or an asset importer) to manage a mapping between the external identity and the content references and GUID:s used in EPiServer CMS to ensure that any links that exists or are created with this data, always reference the same external content. The external identifier should be of type Uri (which can be built from for example guid, int, string etc).&lt;/p&gt;  &lt;p&gt;To test this new service I built a custom content provider called LocalMediaProvider. The idea is that it maps a local file system (like your harddrive) into the asset gadget in EPiServer CMS. It’s similar to the VirtualPathNativeProvider that existed in previous versions of EPiServer.&lt;/p&gt;  &lt;p&gt;Easiest way to integrate the local files would be to create a folder under GlobalAssetsRoot and set the entry point for the provider to that folder. However in my case I wanted to distinguish the local files from other files so I created the entry point outside the asset root. And instead registered an UI component so the local files appears as a separate &amp;quot;tab&amp;quot; in the asset panel. If you try the code and the tab does not show up try to go to &amp;quot;My settings&amp;quot; and select &amp;quot;Reset Views&amp;quot; under &amp;quot;Display options&amp;quot;.&lt;/p&gt;  &lt;p&gt;When going in to the media gadget you can see your local folder structure. In my case I set “C:\” when configuring my provider, in reality you would probably point out a folder structure with for example images.&amp;#160;&amp;#160; &lt;br /&gt;&lt;a href=&quot;/link/74511341fd144b1494305b3253b84479.png&quot;&gt;&lt;img title=&quot;Localmediagadget&quot; style=&quot;display: inline; background-image: none;&quot; border=&quot;0&quot; alt=&quot;Localmediagadget&quot; src=&quot;/link/219ee490005645039a4e0ec1405f2429.png&quot; width=&quot;331&quot; height=&quot;573&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;If you want to try it out the source code is located in &lt;a href=&quot;https://github.com/jbearfoot/LocalMediaProvider&quot;&gt;https://github.com/jbearfoot/LocalMediaProvider&lt;/a&gt;. There you will also find a built nuget package that you can add to your project. It will then include the code to your project in a folder LocalMediaProvider.&lt;/p&gt;  &lt;p&gt;Note that this was just a sample I wrote to test the IdentityMappingService and hence it is not “productified” and all usage of the code is at own risk &lt;img class=&quot;wlEmoticon wlEmoticon-winkingsmile&quot; alt=&quot;Blinkar&quot; src=&quot;/link/9813303ce02042d58f7fb7da4e8b7a63.png&quot; /&gt;. The code consists of three components. First there is a content provider that reads files and folders from the local file system and presents them as ContentFolders and IContentMedia instances. Then there is a UI component that registers a “new” tab in the media gadget. And finally a Initialization module that creates an entry point for the provider, registers the provider and registers some routes for the media.&lt;/p&gt;</id><updated>2014-08-21T10:16:07.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Blob property</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2013/12/Blob-property/" /><id>&lt;p&gt;To be able to support media as content (IContentMedia) we introduced a new property type &lt;b&gt;&lt;i&gt;Blob &lt;/i&gt;&lt;/b&gt;that makes it possible to store binary data related to a content instance. The most obvious usage is through IContentMedia.BinaryData which stores the binary data for a media item. &lt;/p&gt;  &lt;h4&gt;&amp;#160;&lt;/h4&gt;  &lt;h2&gt;ImageDescriptor attribute&lt;/h2&gt;  &lt;p&gt;Another usage of blobs for media is the Thumbnail property for IContentMedia where a thumbnail format of the media is stored. For images the thumbnail is auto generated due to the usage of ImageDescriptor attribute. The base class ImageData looks like:&lt;/p&gt;  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;public class &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;ImageData &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;MediaData&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;IContentImage
    &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;{
        &lt;/span&gt;&lt;span style=&quot;background: white; color: gray;&quot;&gt;/// &amp;lt;summary&amp;gt;
        /// &lt;/span&gt;&lt;span style=&quot;background: white; color: green;&quot;&gt;Gets or sets the generated thumbnail for this media.
        &lt;/span&gt;&lt;span style=&quot;background: white; color: gray;&quot;&gt;/// &amp;lt;/summary&amp;gt;
        &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;ImageDescriptor&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;(Width = 48, Height = 48)]
        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;public override &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;Framework.Blobs.&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;Blob &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;Thumbnail
        {
            &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;get &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;return base&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.Thumbnail;}
            &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;set &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;base&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.Thumbnail = &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;;}
        }
    }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Here we can see that the ImageDescriptor attribute specifies that it should generate a thumbnail in size 48*48. You can override the property and specify the size as you wish. &lt;/p&gt;

&lt;p&gt;You can also have additional Blobs properties like LargeThumbnail, MediumThumbnail etc. with ImageDescriptor attribute on your media type. They will then be autogenerated like Thumbnail.&lt;/p&gt;

&lt;h2&gt;Lazy loading&lt;/h2&gt;

&lt;p&gt;The actual Blob is stored by the configured BlobProvider so in the content database only the URI to the blob is stored. The actual binary data for the blob will not be loaded before OpenRead method is called on the blob instance.&lt;/p&gt;

&lt;h4&gt;&amp;#160;&lt;/h4&gt;

&lt;h2&gt;Blob routing&lt;/h2&gt;

&lt;p&gt;There is a partial route registered that makes it possible to route directly to a blob property on a content instance. The URL pattern is &amp;lt;content URL&amp;gt;/BlobPropertyName. So for example if there is an image with url &lt;a href=&quot;http://mysite/globalassets/myimage.png&quot;&gt;http://mysite/globalassets/myimage.png&lt;/a&gt; then I can route to the thumbnail as &lt;a href=&quot;http://mysite/globalassets/myimage.png/thumbnail&quot;&gt;http://mysite/globalassets/myimage.png/thumbnail&lt;/a&gt;. You can try this by adding “/thumbnail” to any image URL in a CMS 7.5 site. &lt;/p&gt;

&lt;h2&gt;Export-Import support&lt;/h2&gt;

&lt;p&gt;Blob properties are included/handled in export-import meaning the Blobs referenced from Blob properties will automatically be included in the export package. This means e.g. that it is possible to transfer content (including media/blobs) from one site with a specific blob provider (e.g. FileBlobProvider) to a site with another blob provider (e.g. blob provider for Amazon or Azure).&lt;b&gt;&lt;/b&gt;&lt;/p&gt;

&lt;h2&gt;PDF version of page&lt;/h2&gt;

&lt;p&gt;The Blob property is not restricted to be used by only media. It is possible to add a Blob property to any IContent instance. In the example (I used Alloy templates) below I have added a property of type Blob to SitePageData as:&lt;/p&gt;

&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;public virtual &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;Blob &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;PDF { &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;; }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I then added an eventhandler for IContentEvents.PublishedContent where I generate a PDF for the page and stores the PDF in the blob property. I can then view the PDF version of the page by appending “/pdf” to the URL for the page. The code for the example is below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: In the example a package called Pechkin is used to generate the PDF but there are many different PDF generators to choose from.&lt;/p&gt;

&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;ModuleDependency&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;typeof&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;(EPiServer.Web.&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;InitializationModule&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;))]
    &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;public class &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;PDFCreatorModule &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;IInitializableModule
    &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;{
        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;public void &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;Initialize(&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;InitializationEngine &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;context)
        {
            &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;globalConfig = &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;GlobalConfig&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;();
            globalConfig.SetMargins(&lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;Margins&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;(300, 100, 150, 100))
                .SetDocumentTitle(&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(163, 21, 21);&quot;&gt;&amp;quot;Test document&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;)
                .SetPaperSize(&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;PaperKind&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.A3Rotated);

            &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;contentEvents = context.Locate.Advanced.GetInstance&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;IContentEvents&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;&amp;gt;();

            contentEvents.PublishingContent += (sender, args) =&amp;gt;
                {
                    &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;page = args.Content &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;as &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;SitePageData&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;;
                    &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;(page != &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;null &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;&amp;amp;&amp;amp; !page.ProcessedPDF)
                    {
                        args.Items[&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(163, 21, 21);&quot;&gt;&amp;quot;ProcessPDF&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;] = &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;;
                    }
                };
            contentEvents.PublishedContent += (sender, args) =&amp;gt;
            {
                &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;page = args.Content &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;as &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;SitePageData&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;;
                &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;(page != &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;null &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;&amp;amp;&amp;amp; args.Items[&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(163, 21, 21);&quot;&gt;&amp;quot;ProcessPDF&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;] != &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;)
                {
                    context.Locate.Advanced.GetInstance&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;PDFCreator&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;&amp;gt;()
                        .CreatePDF(page, globalConfig, &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;WebClient&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;());
                }
            };
        }

        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;public void &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;Preload(&lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;string&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;[] parameters)
        {}

        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;public void &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;Uninitialize(&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;InitializationEngine &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;context)
        {}
    }

    &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;public class &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;PDFCreator
    &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;{
        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;private &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;IContentRepository &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;_contentRepository;
        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;private &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;BlobFactory &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;_blobFactory;
        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;private &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;UrlResolver &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;_urlResolver;

        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;public &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;PDFCreator(&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;IContentRepository &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;contentRepository, &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;BlobFactory &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;blobFactory, &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;UrlResolver &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;urlResolver)
        {
            _contentRepository = contentRepository;
            _blobFactory = blobFactory;
            _urlResolver = urlResolver;
        }

        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;public virtual void &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;CreatePDF(&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;SitePageData &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;page, &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;GlobalConfig &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;gc, &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;WebClient &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;webClient)
        {
            page = page.CreateWritableClone() &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;as &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;SitePageData&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;;
            page.PDF = _blobFactory.CreateBlob(&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;Blob&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.GetContainerIdentifier(page.ContentGuid), &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(163, 21, 21);&quot;&gt;&amp;quot;.pdf&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;);

            &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;pageUrl = &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;UrlResolver&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.Current.GetUrl(page.ContentLink, page.Language.Name);
            &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;absolutePageUrl = &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;UriSupport&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.CreateAbsoluteUri(pageUrl);
            &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;htmlText = webClient.DownloadString(absolutePageUrl);
            &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;htmlWithAbsoluteUris = MakeUrisAbsoulte(htmlText, &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;SiteDefinition&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.Current.SiteUrl);

            &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;pechin = &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;SynchronizedPechkin&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;(gc);

            &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;oc = &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;ObjectConfig&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;();
            oc.SetCreateExternalLinks(&lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;)
              .SetFallbackEncoding(&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;Encoding&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.Unicode)
              .SetLoadImages(&lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;);

            &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;using &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;writeStream = page.PDF.OpenWrite())
            {
                &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;convertedData = pechin.Convert(oc, htmlWithAbsoluteUris);
                writeStream.Write(convertedData, 0, convertedData.Length);
            }

            page.ProcessedPDF = &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;;
            _contentRepository.Save(page, 
                &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;SaveAction&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.Publish | &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;SaveAction&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.ForceCurrentVersion | &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;SaveAction&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.SkipValidation,
                                    &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;AccessLevel&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.NoAccess);
        }

        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;const string &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;pattern = &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(163, 21, 21);&quot;&gt;@&amp;quot;(?&amp;lt;name&amp;gt;src|href)=&amp;quot;&amp;quot;(?&amp;lt;value&amp;gt;/[^&amp;quot;&amp;quot;]*)&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;;
        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;private string &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;MakeUrisAbsoulte(&lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;string &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;html, &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;Uri &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;baseUri)
        {
            &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;matchEvaluator = &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;MatchEvaluator&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;(
                match =&amp;gt;
                    {
                        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;uri = &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;Uri&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;(match.Groups[&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(163, 21, 21);&quot;&gt;&amp;quot;value&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;].Value, &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;UriKind&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.RelativeOrAbsolute);
                        &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;Uri &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;absoluteUri;
                        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;(!uri.IsAbsoluteUri &amp;amp;&amp;amp; &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;Uri&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.TryCreate(baseUri, uri, &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;out &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;absoluteUri))
                        {
                            &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;name = match.Groups[&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(163, 21, 21);&quot;&gt;&amp;quot;name&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;].Value;
                            &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;return string&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.Format(&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(163, 21, 21);&quot;&gt;&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(60, 179, 113);&quot;&gt;{0}&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(163, 21, 21);&quot;&gt;=\&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(60, 179, 113);&quot;&gt;{1}&lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(163, 21, 21);&quot;&gt;\&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;, name, absoluteUri.AbsoluteUri);
                        }

                        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;return null&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;;
                });
            &lt;/span&gt;&lt;span style=&quot;background: white; color: blue;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;background: white; color: rgb(43, 145, 175);&quot;&gt;Regex&lt;/span&gt;&lt;span style=&quot;background: white; color: black;&quot;&gt;.Replace(html, pattern, matchEvaluator);
        }
    }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;</id><updated>2013-12-16T09:15:34.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Multisite feature in EPiServer 7.5</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2013/12/Multisite-feature-in-EPiServer-75/" /><id>&lt;p&gt;Even in previous version it was possible to have several EPiServer sites sharing the same database and configuration files (often referred as Enterprise setup). However there was a one to one relationship between IIS instance and EPiServer site meaning each EPiServer site needed to have an own IIS instance configured. So even when using same IIS application pool the sites run in different AppDomains. &lt;/p&gt;  &lt;p&gt;One consequence of running in separate AppDomains is that static properties like &lt;strong&gt;PageReference.StartPage&lt;/strong&gt; or &lt;strong&gt;Configuration.Settings.Instance&lt;/strong&gt; will not be shared between sites and hence have different static values in each AppDomain. It also has the consequence that event replication was needed to be configured between the sites to get cache invalidation to work.&lt;/p&gt;  &lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;h2&gt;Multisite in 7.5&lt;/h2&gt;  &lt;p&gt;In EPiServer 7.5 multi-site handling has been changed so now a running EPiServer instance is multi-tenant meaning a single EPiServer application running in one AppDomain can contain several EPiServer sites. &lt;/p&gt;  &lt;p&gt;The take advantage of this the DNS/IIS should be configured so the requests are routed to that IIS application. You can e.g. have a wildcard configuration so all request of *.mydomain.com is routed to the IIS application. Then it will be possible to dynamically create/delete new sites like newcampaign.mydomain.com without doing any IIS/DNS configuration at all.&lt;/p&gt;  &lt;p&gt;It is of course still possible to configure to run sites that share database in separate IIS instances. For example it can be good to separate large sites to different machines (to avoid that they share the same resources like memory). When doing so you need to configure remote events though.&lt;/p&gt;  &lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;h2&gt;Configuration changes&lt;/h2&gt;  &lt;p&gt;Previously site settings (like e.g. SiteUrl, StartPage) where defined in the configuration files. That had the consequence that when a site was added/removed the configuration file had to be updated and hence the applications where restarted. We have removed away site settings (like SiteUrl, StartPage, host mappings etc.) from the configuration files and instead those values are stored in database. This make it possible to add/remove sites dynamically without having to update configuration files and hence application restarts can be avoided&lt;/p&gt;  &lt;p&gt;This also simplifies deployment/development scenarios since the configuration files does not need to contain as much environment specific settings.&lt;/p&gt;  &lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;h2&gt;SiteDefinition&lt;/h2&gt;  &lt;p&gt;To be able to run several sites in the same domain static properties like &lt;b&gt;ContentReference.StartPage&lt;/b&gt; and &lt;b&gt;Settings.Instance.SiteUrl&lt;/b&gt; must return differently depending on context (in previous versions these properties where “truly” static throughout the application). We have achieved this by letting those properties delegate to &lt;b&gt;SiteDefinition.Current &lt;/b&gt;(resides in namespace EPiServer.Web).&lt;/p&gt;  &lt;p&gt;&lt;b&gt;SiteDefinition.Current&lt;/b&gt; is resolved from the request, meaning a comparison will be done where the host from the request will be matched against all sites from &lt;b&gt;SiteDefintionRepository.&lt;/b&gt; The site with a host matching the request will be returned. If no match is found or if the current thread is not executing on a web request the site registered with wildcard host &#39;*&#39; will be returned. If no wildcard site is defined a default &lt;b&gt;SiteDefinition&lt;/b&gt; is returned where common settings like e.g. &lt;b&gt;RootPage&lt;/b&gt; is set but &lt;b&gt;StartPage&lt;/b&gt; will be &lt;b&gt;ContentReference.EmptyReference&lt;/b&gt; and &lt;b&gt;SiteUrl&lt;/b&gt; will be null.&lt;/p&gt;  &lt;p&gt;That means that you can add host &#39;*&#39; to one site if you want that site to be returned from &lt;b&gt;SiteDefintion.Current&lt;/b&gt; when there is no web request, this can be useful e.g. when running scheduled jobs. Another possibility for code that is not running on a web request (like scheduled jobs) is to assign &lt;b&gt;SiteDefinition.Current&lt;/b&gt; then that assignment will be set for that context.&lt;/p&gt;  &lt;p&gt;Also worth noticing is that there is &lt;b&gt;one&lt;/b&gt; initialization for the application where all sites are initialized (unlike before where the initialization where for a specific site since each site run in a separate AppDomain). So if you have some custom initialization module that are site dependent you could use &lt;b&gt;SiteDefinitionRepository.List()&lt;/b&gt; to get a list of all defined sites.&lt;/p&gt;  &lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;h2&gt;Site Management&lt;/h2&gt;  &lt;p&gt;Sites are managed in admin mode under “Manage Websites” in admin mode. Here you can create new sites, delete unused sites and configure sites (for example specify language-host mappings). So by default is site handling a task for administrators. &lt;/p&gt;  &lt;p&gt;However it is possible to let site creation be done by editors. One way to achieve this is to set up an event handler for &lt;strong&gt;IContentEvents.PublishedContent&lt;/strong&gt; and in the event handler check if the content is of your StartPage type and if so creating a new site by storing a new instance towards SiteDefinitionRepository.&lt;/p&gt;</id><updated>2013-12-11T17:50:10.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Routing changes in 7.5</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2013/12/Routing-changes-in-75/" /><id>&lt;p&gt;There are some changes that have been done regarding routing and template selection in EPiServer 7.5. Here is a summary of the most significant changes.&lt;/p&gt;  &lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;h2&gt;Routing to files/media&lt;/h2&gt;  &lt;p&gt;In EPiServer 7.5 the handling of files used in content (typically handled through FileManager) have been changed from being based on VirtualPathProviders to be based on content (IContent implementations). This means files share much of the functionality like access rights, versioning etc. as other content types (as e.g. Pages, Blocks). This also means that files are routed to in the same way as e.g. pages.&lt;/p&gt;  &lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;h2&gt;Lower-Case URLs&lt;/h2&gt;  &lt;p&gt;By default in EPiServer 7.5 URL segments for content will be generated in lower-case. It is possible to allow upper case characters in URL segments by setting &lt;strong&gt;EPiServer.Web.UrlSegment.UseLowerCaseSegments&lt;/strong&gt; to false.&lt;/p&gt;  &lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;h2&gt;Trailing slash&lt;/h2&gt;  &lt;p&gt;By default URLs in EPiServer is ended with a trailing slash (except for media/files). It is possible change the behavior by setting &lt;strong&gt;EPiServer.Web.Routing.ContentRoute.UseTrailingSlash&lt;/strong&gt; to false.&lt;/p&gt;  &lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;h2&gt;Direct routing to Blobs&lt;/h2&gt;  &lt;p&gt;We have introduced a partial router that handles direct routing to Blob properties. You can try this by adding “/thumbnail” to any image url. I will in a later post go into Blobs in more detail.&lt;/p&gt;  &lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;h2&gt;Performance improvements&lt;/h2&gt;  &lt;p&gt;If you run SQL profiler while doing some request against a CMS 7 site you can notice some calls to a stored procedure to match for simple address. You do not be to worried over this since that stored procedure is fast but in 7.5 we have introduced a cache for this calls. Another change is that incoming routing is not using IContentLoader.GetChildren (which is the case in CMS7), instead it uses a new method IContentLoader.GetBySegment. This method is not dependent on the number of items on a certain level in the content tree, so especially&amp;#160; when routing through a structure with many items at the same level 7.5 routes much faster. This new method is also used when generating URL segments so creating/saving content instances(especially where there are many items on the same level) is also faster.&lt;/p&gt;  &lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;h2&gt;UrlResolver&lt;/h2&gt;  &lt;p&gt;The class &lt;strong&gt;EPiServer.Web.UrlResolver&lt;/strong&gt; can be used both to generate URLs for content items and also get the content item for a given URL. We have added some methods to make it easier to control the URL generation. For example it is possible to specify for which context (View, Edit, Preview) the URL should be constructed for. We have also added a static property&lt;strong&gt; Current&lt;/strong&gt; to UrlResolver make it easier to use in cases where testability is not applicable/important.&lt;/p&gt;  &lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;h2&gt;Partial routing to IContent instances&lt;/h2&gt;  &lt;p&gt;Some changes have been done in the case where partial routing is used to route to IContent instances. Now the extension method RequestContext.GetContentLink() will return the link to the partial routed content instance (and not the “ordinary routed content” as in CMS7). You can however get the “ordinary routed content” that was routed to by using extension method RequestContext.GetOriginalRoutedLink().&lt;/p&gt;  &lt;p&gt;This has the consequence that &lt;b&gt;ContentRouteHelper&lt;/b&gt; will also give the partial routed content while&lt;b&gt; PageRouteHelper&lt;/b&gt; will give either the partial routed content (if it is a page) or the page where partial routing took of (given that it was a page) or StartPage as final fallback.&lt;/p&gt;  &lt;p&gt;The reason for this is that it should be possible to use for example the new base class &lt;b&gt;ContentPageBase&amp;lt;TContent&amp;gt;&lt;/b&gt; or &lt;b&gt;ContentPageBase&amp;lt;PageData, TContent&amp;gt;&lt;/b&gt; which then will offer both a CurrentPage and a CurrentContent. In MVC the similarity is to have two parameters currentPage and currentContent that will be assigned by the model binder.&lt;/p&gt;  &lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;h2&gt;Routing to “classic” links&lt;/h2&gt;  &lt;p&gt;Previously it was possible to make a request to a webform page with a classic link like e.g. &lt;a href=&quot;http://localhost:17000/Templates/Page.aspx?id=17&amp;amp;epslanguage=en&quot;&gt;http://localhost:17000/Templates/Page.aspx?id=17&amp;amp;epslanguage=en&lt;/a&gt;. By default this will not work anymore since the implementation of CurrentPage in PageBase does not pay attention to query parameters any more (instead it relies that the routing has set the routed content), &lt;/p&gt;  &lt;p&gt;It is however possible to register a special route to handle “classic” links, this can be done like:&lt;/p&gt;  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: black&quot;&gt; &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;protected override void &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;RegisterRoutes(System.Web.Routing.RouteCollection routes)
        {
            &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;base&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;.RegisterRoutes(routes);
            routes.Insert(0, ServiceLocator.Current.GetInstance&amp;lt;ClassicLinkRoute&amp;gt;());
        }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h3&gt;&amp;#160;&lt;/h3&gt;

&lt;h2&gt;Template selection for on-page edit and preview&lt;/h2&gt;

&lt;p&gt;Previously when a template was selected for on-page edit the system first tried to select the default template (that is without any tag). If no such template was found a selection was done for a template with tag “Preview” (this is how on-page editing for shared blocks work). &lt;/p&gt;

&lt;p&gt;This has been changed so now in on-page edit mode a selection is first done for a template with tag “Edit”, if no such is found a fallback is done for first default template(no tag) and finally a template with tag “Preview”. And in preview mode a selection is done for a template with tag “Preview” with fallback to default.&lt;/p&gt;

&lt;p&gt;This makes it possible to for example have three different templates for a page, one tagged with “Edit”, one with “Preview” and one default. In most cases a “Preview” template is probably not needed but a “Edit” template can be useful. One use case is to expose properties on the “Edit” template that is not part of the normal template used in view mode. This makes it possible for editors to edit these properties directly on page without having to go to “All properties”/Forms mode.&lt;/p&gt;

&lt;h3&gt;&amp;#160;&lt;/h3&gt;

&lt;h2&gt;Strict language routing&lt;/h2&gt;

&lt;p&gt;The routing has been changed so it is more strict due to language handling (partly introduced already in patches to EPiServer 7). As an example say that there is a page under start page named &amp;quot;News&amp;quot; in English and &amp;quot;Nyheter&amp;quot; in Swedish. Previously the following URLs where handled like (given that no language mapping is defined for site hosts):&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;http://sitehost/News/ (page in language given by context typically globalization setting in web.config e.g. en) &lt;/li&gt;

  &lt;li&gt;http://sitehost/en/News/ (page in english) &lt;/li&gt;

  &lt;li&gt;http://sitehost/sv/Nyheter/ (page in swedish) &lt;/li&gt;

  &lt;li&gt;http://sitehost/Nyheter/ (page in english since no language info in URL get language as in point 1) &lt;/li&gt;

  &lt;li&gt;http://sitehost/en/Nyheter/ (page in english since language segment states english) &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With the new strict language routing the above URLs will be handled as:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;http://sitehost/News/ (404 since when not having language-host mapping in config language segment must be present, unless site have only one language) &lt;/li&gt;

  &lt;li&gt;http://sitehost/en/News/ (page in english) &lt;/li&gt;

  &lt;li&gt;http://sitehost/sv/Nyheter/ (page in swedish) &lt;/li&gt;

  &lt;li&gt;http://sitehost/Nyheter/ (404 as in 1.) &lt;/li&gt;

  &lt;li&gt;http://sitehost/en/Nyheter/ (404 since language for page with URL segment does not match language segment). &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Another change is that when a language mapping is defined for a host, say for example that host “sitehost” is mapped to “en” then an URL like http://sitehost/en/News/ will give a 404 since when there is a host mapping that defines a language then that language should not be present in URL.&lt;/p&gt;

&lt;p&gt;There is a configuration setting &amp;quot;strictLanguageRouting&amp;quot; on configuration element applicationSettings that can be set to false to get old more tolerant behavior.&lt;/p&gt;</id><updated>2013-12-06T21:35:36.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Deployment and Cloud support</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2013/12/Deployment-and-Cloud-support/" /><id>&lt;p&gt;This post is most an overview of the changes we have done around deployment and how a site is “packaged”. There are much more information about deployment and cloud support in the CMS SDK under “Developer Guide/Deployment”. For example can information/examples about deployments to Azure and Amazon be found there.&lt;/p&gt;  &lt;h2&gt;XCopy enabled deployment&lt;/h2&gt;  &lt;p&gt;In EPiServer 7.5 we have changed how a site is “packaged” so deployment of an EPiServer CMS site can be done through XCOPY deployment simply by copying application files. An XCOPY-style file transfer simplifies deployment and maintenance of EPiServer sites since no registry entries are created, and no shared components are registered. Examples of XCOPY-style hosting is Azure Web Sites and Amazon Elastic Beanstalk, where basically only a IIS instance is provided, and it is not possible to run an installation setup procedure.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: We do not say that you should use XCOPY deployment as such, you should of course use the deployment that suits your hosting environment. But making deployment copy enabled should benefit other deployments as well like e.g. MSDeploy, FTP and external deployment tools.&lt;/p&gt;  &lt;p&gt;Another benefit of the XCOPY architecture in EPiServer CMS is that there is no machine- or site-specific information stored in configuration files, making it possible to use a shared folder for multiple servers. During development in a shared environment with source control, developers can keep configuration files checked in and still be able to create a site which can be duplicated in a multi-site deployment.&lt;/p&gt;  &lt;p&gt;Another change that is related to copy enabled deployment is that we have removed the usage of Windows service for CMS. This means that the scheduled jobs are maintained within the web application it self. &lt;/p&gt;  &lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;h2&gt;Cloud support&lt;/h2&gt;  &lt;p&gt;Another change we have done to make it easier to scale an EPiServer installation by adding/removing IIS instances/machines is that we have changed so “services” like Blob storage (replaces previously used VPP based files) and event management (between sites) is provider based. The idea is that one IIS instance running the site only have knowledge about the services and not direct knowledge about other running web site instances. Then it is possible to add/remove one instance without having to touch the other running instance. A conceptual picture of this is:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/bc50e7747f624cc1862af43343d6bbc2.jpg&quot;&gt;&lt;img title=&quot;clip_image002&quot; style=&quot;border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; padding-top: 0px; padding-left: 0px; display: inline; padding-right: 0px; border-top-width: 0px&quot; border=&quot;0&quot; alt=&quot;clip_image002&quot; src=&quot;/link/72b540bddef941d7bce8e5b8790f6767.jpg&quot; width=&quot;522&quot; height=&quot;382&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;There are separate NuGet packages EPiServer.Azure and EPiServer.Amazon in our feed that contain Blob providers and event providers for each of those environments. &lt;/p&gt;</id><updated>2013-12-05T09:55:34.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Working with Media programmatically</title><link href="https://world.optimizely.com/blogs/Johan-Bjornfot/Dates1/2013/12/Working-with-Media-programmatically/" /><id>&lt;p&gt;Prior to version 7.5, files in EPiServer CMS (as exposed in the old file manager) were handled by a VPP (Virtual Path Providers) system. In the latest version of EPiServer a new media file system with a new user interface is introduced. Content stored in this system is referred to as “media”. This system is based on the same content (IContent implementations) system used for blocks and pages, as well as products from the catalog in Commerce. This means that files shares same support for routing, custom properties, typed models, custom renderings, security etc. as other content types.&lt;/p&gt;  &lt;p&gt;To work programmatically with media is much like working with other content types (e.g. pages). For example are the CRUD operations done through IContentRepository. In this post I will go through some of the interfaces/base classes used for media and give some examples on how to programmatically work with media.&lt;/p&gt;  &lt;h2&gt;&amp;#160;&lt;/h2&gt;  &lt;h2&gt;IContentMedia&lt;/h2&gt;  &lt;p&gt;The requirement for a media type is that it implements IContentMedia which is defined as:&lt;/p&gt;  &lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;public interface &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;IContentMedia &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;IContent&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;IBinaryStorable
    &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;background: white; color: gray&quot;&gt;
        &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;Blob &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;Thumbnail { &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;; }&lt;/span&gt;&lt;span style=&quot;background: white; color: gray&quot;&gt;
        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;string &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;MimeType { &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;; }
    }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can see that IContentMedia extends IContent and also IBinaryStorable which is defined as:&lt;/p&gt;

&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;public interface &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;IBinaryStorable
    &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;background: white; color: gray&quot;&gt;
        &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;Blob &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;BinaryData { &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;;}
&lt;/span&gt;&lt;span style=&quot;background: white; color: gray&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;Uri &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;BinaryDataContainer { &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;; }
    }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The Property &lt;strong&gt;BinaryData&lt;/strong&gt; of type &lt;strong&gt;Blob &lt;/strong&gt;(see class below) is used to handle the actual binary content of the media. The property &lt;strong&gt;BinaryDataContainer &lt;/strong&gt;is the Uri for the container containing the Blob. All binaries for a content instance (including versions and languages)&lt;strong&gt;&amp;#160;&lt;/strong&gt;are stored in a common container. The definition of Blob looks like (I have omitted the static methods):&lt;/p&gt;

&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;public class &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;Blob
&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;{
        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;public &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;Uri &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;ID { &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;; }&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;
        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;public virtual &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;Stream &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;OpenRead();
        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;public virtual &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;Stream &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;OpenWrite();&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;
        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;public virtual void &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;Write(&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;Stream &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;data);
}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So a blob instance basically contains stream based Read and Write operations. The actual Blob instance is delivered by the configured &lt;strong&gt;BlobProvider&lt;/strong&gt;. The default blob provider stores the binary data on disk (there is a subfolder blobs in the folder specified by attribute basePath on configuration element appData). The NuGet packages EPiServer.Azure and EPiServer.Amazon contains provider to store binary data in Azure Blob storage respectively Amazon S3. &lt;/p&gt;

&lt;h2&gt;&amp;#160;&lt;/h2&gt;

&lt;h2&gt;Defining a media type&lt;/h2&gt;

&lt;p&gt;A media type is defined by having a class implementing IContentMedia and decorated with ContentTypeAttibute. The attribute MediaDescriptorAttribute can be used to map which extensions a certain type handles. There are some base classes MediaData, ImageData and VideoData that can be used to specify media types. So for example a project can have types defined as:&lt;/p&gt;

&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;    [&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;ContentType&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;(GUID = &lt;/span&gt;&lt;span style=&quot;background: white; color: #a31515&quot;&gt;&amp;quot;EE3BD195-7CB0-4756-AB5F-E5E223CD9820&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;)]
    &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;public class &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;GenericMedia &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;MediaData
    &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;{
&lt;/span&gt;&lt;span style=&quot;background: white; color: gray&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;public virtual &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;String &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;Description { &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;; }
    }

    [&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;ContentType&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;(GUID = &lt;/span&gt;&lt;span style=&quot;background: white; color: #a31515&quot;&gt;&amp;quot;0A89E464-56D4-449F-AEA8-2BF774AB8730&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;)]
    [&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;MediaDescriptor&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;(ExtensionString = &lt;/span&gt;&lt;span style=&quot;background: white; color: #a31515&quot;&gt;&amp;quot;jpg,jpeg,jpe,ico,gif,bmp,png&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;)]
    &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;public class &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;ImageFile &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;ImageData
    &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;background: white; color: gray&quot;&gt;
        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;public virtual string &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;Copyright { &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;; }
    }

    [&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;ContentType&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;(GUID = &lt;/span&gt;&lt;span style=&quot;background: white; color: #a31515&quot;&gt;&amp;quot;85468104-E06F-47E5-A317-FC9B83D3CBA6&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;)]
    [&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;MediaDescriptor&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;(ExtensionString = &lt;/span&gt;&lt;span style=&quot;background: white; color: #a31515&quot;&gt;&amp;quot;flv,mp4,webm&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;)]
    &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;public class &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;VideoFile &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;VideoData
    &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;background: white; color: gray&quot;&gt;
        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;public virtual string &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;Copyright { &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;; }&lt;/span&gt;&lt;span style=&quot;background: white; color: gray&quot;&gt;
        &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;UIHint&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;UIHint&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;.Image)]
        &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;public virtual &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;ContentReference &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;PreviewImage { &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;; }
    }&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;&amp;#160;&lt;/h2&gt;

&lt;h2&gt;Creating a new media instance&lt;/h2&gt;

&lt;p&gt;Below is an example on how to create a new media instance. Here the media item is created under SiteDefinition.Current.GlobalAssetRoot which is the folder for assets that is shared between sites (this is the root for the media gadget). To structure media instances of EPiServer.Core.ContentFolder can be created.&lt;/p&gt;

&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;contentRepository = &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;ServiceLocator&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;.Current.GetInstance&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;IContentRepository&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;&amp;gt;();
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;blobFactory = &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;ServiceLocator&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;.Current.GetInstance&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;BlobFactory&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;&amp;gt;();

&lt;/span&gt;&lt;span style=&quot;background: white; color: green&quot;&gt;//Get a new empty file data
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;file1 = contentRepository.GetDefault&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;GenericFile&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;SiteDefinition&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;.Current.GlobalAssetsRoot);
file1.Name = &lt;/span&gt;&lt;span style=&quot;background: white; color: #a31515&quot;&gt;&amp;quot;Readme.txt&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;;
            
&lt;/span&gt;&lt;span style=&quot;background: white; color: green&quot;&gt;//Create a blob in the binary container
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;blob = blobFactory.CreateBlob(file1.BinaryDataContainer, &lt;/span&gt;&lt;span style=&quot;background: white; color: #a31515&quot;&gt;&amp;quot;.txt&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;);
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;using &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;s = blob.OpenWrite())
{
     &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;StreamWriter &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;w = &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;StreamWriter&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;(s);
     w.WriteLine(&lt;/span&gt;&lt;span style=&quot;background: white; color: #a31515&quot;&gt;&amp;quot;Hello world&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;);
     w.Flush();
}

&lt;/span&gt;&lt;span style=&quot;background: white; color: green&quot;&gt;//Assign to file and publish changes
&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;file1.BinaryData = blob;
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;file1ID = contentRepository.Save(file1, &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;SaveAction&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;.Publish);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;&amp;#160;&lt;/h2&gt;

&lt;h2&gt;Get media type from extension&lt;/h2&gt;

&lt;p&gt;There is a ContentMediaResolver that can be used to resolve which content type to use for a certain extension. See below:&lt;/p&gt;

&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;contentRepository = &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;ServiceLocator&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;.Current.GetInstance&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;IContentRepository&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;&amp;gt;();
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;contentTypeRepository = &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;ServiceLocator&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;.Current.GetInstance&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;IContentTypeRepository&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;&amp;gt;();
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;mediaDataResolver = &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;ServiceLocator&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;.Current.GetInstance&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;ContentMediaResolver&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;&amp;gt;();&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;

&lt;/span&gt;&lt;span style=&quot;background: white; color: green&quot;&gt;//Get a suitable MediaData type from extension
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;mediaType = mediaDataResolver.GetFirstMatching(&lt;/span&gt;&lt;span style=&quot;background: white; color: #a31515&quot;&gt;&amp;quot;.txt&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;);
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;contentType = contentTypeRepository.Load(mediaType);
&lt;/span&gt;&lt;span style=&quot;background: white; color: green&quot;&gt;//Get a new empty file data
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;media = contentRepository.GetDefault&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;IContentMedia&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;SiteDefinition&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;.Current.GlobalAssetsRoot, contentType.ID);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;strong&gt;&lt;/strong&gt;

&lt;h2&gt;&amp;#160;&lt;/h2&gt;

&lt;h2&gt;Replace the binary data for a media item&lt;/h2&gt;

&lt;p&gt;When a binary data is to be replaced for a media item a new Blob instance should be created. That is you should &lt;strong&gt;not&lt;/strong&gt; call OpenWrite on the existing blob instance. The reason for this is to support versioning so that if an editor reverts back to an old version the binary data should follow. Normally you should not need to bother about deleting Blobs, there is a scheduled jobs that takes care of deleting unused Blobs. Below is an example on how to replace the binary data for a media in a new version:&lt;/p&gt;

&lt;pre class=&quot;language-csharp&quot;&gt;&lt;code&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;contentRepository = &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;ServiceLocator&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;.Current.GetInstance&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;IContentRepository&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;&amp;gt;();
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;blobFactory = &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;ServiceLocator&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;.Current.GetInstance&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;BlobFactory&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;&amp;gt;();

&lt;/span&gt;&lt;span style=&quot;background: white; color: green&quot;&gt;//the file to update, not hardcoded of course
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;fileID = &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;ContentReference&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;(444);

&lt;/span&gt;&lt;span style=&quot;background: white; color: green&quot;&gt;//Get the file
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;file1 = contentRepository.Get&amp;lt;&lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;GenericFile&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;&amp;gt;(fileID).CreateWritableClone() &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;as &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;GenericFile&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;;

&lt;/span&gt;&lt;span style=&quot;background: white; color: green&quot;&gt;//Create new blob
&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;file1.BinaryData = blobFactory.CreateBlob(file1.BinaryDataContainer, &lt;/span&gt;&lt;span style=&quot;background: white; color: #a31515&quot;&gt;&amp;quot;.txt&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;);
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;using &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;s = file1.BinaryData.OpenWrite())
{
    &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;StreamWriter &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;w = &lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;new &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;StreamWriter&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;(s);
    w.WriteLine(&lt;/span&gt;&lt;span style=&quot;background: white; color: #a31515&quot;&gt;&amp;quot;Hello world&amp;quot;&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;);
    w.Flush();
}

&lt;/span&gt;&lt;span style=&quot;background: white; color: green&quot;&gt;//publish new version
&lt;/span&gt;&lt;span style=&quot;background: white; color: blue&quot;&gt;var &lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;file1ID = contentRepository.Save(file1, &lt;/span&gt;&lt;span style=&quot;background: white; color: #2b91af&quot;&gt;SaveAction&lt;/span&gt;&lt;span style=&quot;background: white; color: black&quot;&gt;.Publish);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;h2&gt;Working with content assets&lt;/h2&gt;

&lt;p&gt;In previous versions it was possible to have a local VPP folder for a content where files related to that content could be stored. Now with media based assets a content instance that implements &lt;b&gt;EPiServer.Core.IResourcable&lt;/b&gt; can have related assets (media, blocks etc.) stored in an instance of &lt;b&gt;EPiServer.Core.ContentAssetFolder&lt;/b&gt;. Resources stored as content assets are to be seen as exclusive assets for that content instance and hence the resources are not selectable from other content instances.&lt;/p&gt;

&lt;p&gt;The method &lt;strong&gt;GetOrCreateAssetFolder &lt;/strong&gt;on class &lt;b&gt;EPiServer.Core.ContentAssetHelper&lt;/b&gt; can be used to get the asset folder for a content item.&lt;/p&gt;</id><updated>2013-12-03T19:36:48.0000000Z</updated><summary type="html">Blog post</summary></entry></feed>