Posts

Showing posts from 2024

Optimizely Content Graph: minimal setup for testing

Image
 1. Create a test page: [ContentType(DisplayName = "Test Page", GUID = "462d1812-7385-42c3-8073-c1b7481e7b21", Description = "TestPage", AvailableInEditMode = true, GroupName = GroupNames.Content)] public class TestPage : PageData { [CultureSpecific] [UIHint(UIHint.Textarea)] [Display(Name = "Test", GroupName = SystemTabNames.Content, Order = 1)] public virtual string Test { get; set; } } 2. Add this in Startup services.AddContentGraph(configureOptions: options => { options.SynchronizationEnabled = false; options.Include.ContentTypes = new string[] { typeof(TestPage).Name, }; options.OnlySyncContentTypesInWhitelistToSchema = true; options.ContentVersionSyncMode = Optimizely.ContentGraph.Cms.Configuration.ContentVersionSyncMode.PublishedOnly; }); 3. Create a test page in UI    4. Run the index job again {      "took": 0,  ...

Episerver Commerce: Creating a new block

Image
Refer to this blog post:  https://world.optimizely.com/blogs/david-harlow/dates/2018/3/extending-commerce---content-area-functionality/ By default, content areas in Episerver commerce items such as products and variants don't display the option for creating a new block, and only allows for blocks to be dragged in, as seen below. However, an extremely simple solution to change this default behavior is to inherit from IResourceable on your product/variant which will require the interface member ContentAssetsID to be declared which can simply be scaffolded to false, and this will be all the code required to display the content area as expected! public class FashionProduct : ProductContent, IResourceable {      [Editable(false)]      [ScaffoldColumn(false)]      public virtual string ProductContentAssetId { get; set; }      [Ignore]      public Guid ContentAssetsID ...

Episerver MatchNodeOrCatalog: Crashes due to (0xC00000FD - Stack Overflow, 0x800703E9 - Recursion too deep; the stack overflowed.)

Image
Looking at the crash dump, the stack trace pointing to  MatchNodeOrCatalog : FaultingExceptionFrame HelperMethodFrame_PROTECTOBJ EPiServer.Core.Internal.ContentCacheKeyCreator.CreateMasterLanguageCacheKey(EPiServer.Core.ContentReference) EPiServer.Core.Internal.ContentInstanceCache.TryGet(EPiServer.Core.ContentReference, System.String, EPiServer.Core.IContent ByRef) EPiServer.Core.ContentProvider.LoadContentFromCacheOrRepository(EPiServer.Core.ContentReference, EPiServer.Core.ILanguageSelector) EPiServer.Core.Internal.ProviderPipelineImplementation.GetItem(EPiServer.Core.ContentProvider, EPiServer.Core.ContentReference, EPiServer.Core.LoaderOptions) EPiServer.Core.Internal.DefaultContentLoader.TryGet[[System.__Canon, mscorlib]](EPiServer.Core.ContentReference, EPiServer.Core.LoaderOptions, System.__Canon ByRef) StubHelperFrame Avensia.EpiFoundation.ContentProcessing.DependencyTracking.DependencyTrackingContentLoader.TryGet[[System.__Canon, mscorlib]](EPiServer.Core.ContentR...

Access permission to Commerce Customize left side tabs

Image
  Check the the access permission of the left menu Add a custom PermissionTypes to the code base: [PermissionTypes] public static class ProductPermissions { static ProductPermissions() { ProductView = new PermissionType(Permissions.GroupName, "product:mng:view"); } public static PermissionType ProductView { get; private set; } }     Add permission in all link ids in leftmnu.xml:

Episerver Commerce Report: Sales by day

Image
  We have an option TimeRangesInDays that generate reports, for example 30, 90, or 180 days. https://docs.developers.optimizely.com/customized-commerce/docs/option-configuration-classes   So when you run the job "Collect Order Data for Reports" it will update order data based on TimeRangesInDays to the table OrderReportData, then that data will be used in procedure [ecf_OrderReportData_AggregateByDay] when you generate the report     In case you want to change the sort order, you can modify the procedure with  OrderCreated DESC ALTER PROCEDURE [dbo].[ecf_OrderReportData_AggregateByDay]  @TimeZoneOffset DECIMAL(38, 9) = 0  AS  BEGIN  SELECT  CONVERT(DATE, DATEADD(minute, @TimeZoneOffset, OrderCreated)) AS OrderCreated,  MarketId,  Currency,  Site,  COUNT(OrderGroupId) AS NumOfOrders,  SUM(TotalQuantity) AS NumOfItems,  SUM(TaxTotal) AS TaxTotal,  SUM(ShippingTotal) as ShippingTotal,  SUM(Han...

Episerver: Date format

The UI language is controlled by the user settings and will default to use whatever is configured in the web.config in the uiCulture attribute on the globalization element: https://docs.developers.optimizely.com/content-management-system/docs/globalization   So you may change the globalization config using the solution below: If that is CMS 11, add this code part to the web.config: <globalization culture="en-AU" uiCulture="en-AU" requestEncoding="utf-8" responseEncoding="utf-8" resourceProviderFactoryType="EPiServer.Framework.Localization.LocalizationServiceResourceProviderFactory, EPiServer.Framework.AspNet" /> If that is CMS 12, configure it in code at Startup.ConfigureServices method: //change the date format globally services.Configure<GlobalizationSettingsOptions>(o => { o.CultureLanguageCode = "en-AU"; o.UICultureLanguageCode = "en-AU"; }); or in appsettings.json: { "EPiServer...

“An item with the same key has already been added. Key: PageDescription”

Image
  “An item with the same key has already been added. Key: PageDescription ” System.ArgumentException: at System.ThrowHelper.ThrowAddingDuplicateWithKeyArgumentException (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e) at System.Collections.Generic.Dictionary`2.TryInsert (System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e) at Mediachase.MetaDataPlus.Configurator.MetaObjectDB.LoadMetaObjectData (Mediachase.MetaDataPlus, Version=14.15.2.0, Culture=neutral, PublicKeyToken=41d2e7a615ba286c) at Mediachase.MetaDataPlus.Internal.CatalogMetaObjectRepository.DoLoadFromDb (Mediachase.MetaDataPlus, Version=14.15.2.0, Culture=neutral, PublicKeyToken=41d2e7a615ba286c) We could use this query to find the content that caused the error: SELECT TOP(1000) ObjectId, MetaFieldName, COUNT(*) AS Count FROM [dbo].[CatalogContentProperty] Where MetaFieldName = ' PageDescription ' GROUP BY ObjectId, MetaFie...

Remove metafield from product content

Even when you remove the code of the  meta field from product content ,  it's still there in the database.  So we need the scripts to complete removing them in both Commerce and CMS: For Commerce: DECLARE @MetaFieldId INT = 80  DELETE FROM MetaDictionary WHERE MetaFieldId = @MetaFieldId  DELETE FROM CatalogContentProperty WHERE MetaFieldId = @MetaFieldId  DELETE FROM ecfVersionProperty WHERE MetaFieldId = @MetaFieldId  DELETE FROM MetaClassMetaFieldRelation WHERE MetaFieldId = @MetaFieldId  DELETE FROM MetaField WHERE MetaFieldId = @MetaFieldId  EXEC mdpsp_sys_ClearMetaAttribute @MetaFieldId, 2 For CMS: exec netPropertyDefinitionDelete @PropertyDefinitionID=2699     If the meta field is not completely removed, the meta field will be re-creating/re-appearing in `tblPropertyDefinition` in CMS when you restart the site: declare @p1 int  set @p1=2702  declare @p16 int  set @p16=7  declare @p17 int  set @p17=NULL...

DnSpy: Getting Started

Image
  You can setup the website in your local environment and use the DnSpy tool to debug to any library   without its source code.    Please refer the belows steps to know how to debug with DnSpy: 1- Download the dnSpy ( https://github.com/dnSpy/dnSpy/releases/tag/v6.1.8 )  to your computer and  Run the dnSpy.exe as Administrator 2- Select Debug > Attach to Process, choose  w3wp.exe or iisexpress.exe 3- Select Debug > Windows > Modules tab window, search the customer DLL filename and copy the file path. This path is the actual the assembly runs in IIS website. Depend on your case, choose the *.dll file 4- Open this Dll file path in dnSpy, go to the class / method we want to debug () 5- Set the Breakpoint and start Debug like in the Visual Studio

Episerver ServiceAPI: Create a custom endpoint

Image
In some cases, you uploaded an asset through Service API. And then you want to update its properties later. You can create a custom endpoint to implement it and we want to reuse the authentication, routing  of ServiceAPI: https://github.com/KhanhPham2411/Episerver-util-api/blob/master/service-api/ItemAssetController using EPiServer.ServiceApi.Configuration; using EPiServer.ServiceApi.Validation; using EPiServer.ServiceApi.Commerce.Controllers.Catalog; using ControllerBase = EPiServer.ServiceApi.Commerce.Controllers.Catalog.ControllerBase; using AuthorizePermissionAttribute = EPiServer.ServiceApi.Configuration.AuthorizePermissionAttribute; using EPiServer.ServiceApi.Commerce; using Foundation.Features.Media; using EPiServer.DataAccess; using EPiServer.Security; using System.Configuration.Provider; namespace Foundation.Custom {     [Route("episerverapi/commerce")]     [RequireHttpsOrClose]     [ValidateReadOnlyMode(AllowedVerbs = HttpVerbs.Get)]   ...