Pages

31 August, 2017

Automatically create new version for Lock & Edit without workflow

Sitecore will create a new version on Lock and Edit if the item is tied to a workflow. For our case, version has to be created even without using workflow. As mentioned by Dylan here, we can override the default behavior of Sitecore. Here we overridden the “Checkout” command which is executed on Lock & Edit.

Added a setting called EnableAddVersionWithoutWorkflow as a flag to enable this feature. If it is true, it will add a version and lock the new version for the user.

Note: By default, only a non-admin user will see the lock and edit button for an item.

if (!item.Locking.IsLocked()) {
  Log.Audit(this, "Start editing: {0}", new string[] {
    AuditFormatter.FormatItem(item)
  });
  if (Context.User.IsAdministrator) {
    item.Locking.Lock();
  }
  //Add new version if the custom flag is true
  else if (bool.Parse(Settings.GetSetting("EnableAddVersionWithoutWorkflow", "false"))) {
    Error.AssertObject(item, "item");
    if (StandardValuesManager.IsStandardValuesHolder(item)) {
      this.Lock(item);
    }
    Item item2 = item.Versions.AddVersion();
    if (item2 != null) {
      item = this.Lock(item2);
    }
  }
  //Add new version if the custom flag is true
  else {
    item = Context.Workflow.StartEditing(item);
  }
  Context.ClientPage.SendMessage(this, string.Concat(new object[] {
    "item:startediting(id=",
    item.ID,
    ",version=",
    item.Version,
    ",language=",
    item.Language,
    ")"
  }));

02 August, 2017

Access denied when attaching new media item.

When a Sitecore non-admin user tries to attach a media item, access denied error appears. 
This is due to incorrect Security settings in Sitecore. My Sitecore Version:  8.1 (rev. 160519)

Solution by Kasaku

3272 11:36:34 ERROR Application error.
Exception: System.Web.HttpUnhandledException
Message: Exception of type 'System.Web.HttpUnhandledException' was thrown.
Source: System.Web
   at System.Web.UI.Page.HandleError(Exception e)
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
   at System.Web.UI.Page.ProcessRequest()
   at System.Web.UI.Page.ProcessRequest(HttpContext context)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

Nested Exception

Exception: System.Reflection.TargetInvocationException
Message: Exception has been thrown by the target of an invocation.
Source: mscorlib
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder
   , Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at Sitecore.Web.UI.Sheer.ClientPage.OnLoad(EventArgs e)
   at Sitecore.Shell.Applications.Dialogs.Attach.AttachPage2.OnLoad(EventArgs e)
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

Nested Exception

Exception: Sitecore.Exceptions.AccessDeniedException
Message: Application access denied.
Source: Sitecore.Kernel
   at Sitecore.Diagnostics.Assert.HasAccess(Boolean accessAllowed, String message)
   at Sitecore.Shell.Applications.Dialogs.Attach.AttachForm.OnLoad(EventArgs e)

29 July, 2017

Sitecore – Contextual shortcut menu

This is a simple idea to bring few chunk items into the contextual menu. It has Layout Details, Publish Item, Preview, Experience Editor, Display name. You can download the package here


10 April, 2017

Redirect restricted media items with ReturnURL

Sitecore can redirect the user to login page if the requested item is restricted for anonymous users. This can be done in the Site configuration. 
requireLogin="true"
loginPage="/redirectpage"
There are two differences in this redirection. For Sitecore item, it will be redirected with returnURL querystring with source url. For Media item, querystring is not added. In one of the project, we had to handle the redirection based on the source url for the Sitecore Media items. To achieve this, MediaRequestHandler can be modified and it will return a query parameter with source URL. Please make sure to update the <handler> with the new class and assembly name. 

  protected override bool DoProcessRequest(HttpContext context) {
	Assert.ArgumentNotNull(context, "context");
	MediaRequest mediaRequest = MediaManager.ParseMediaRequest(context.Request);
	if (mediaRequest == null) {
		return false;
	}
	Media media = MediaManager.GetMedia(mediaRequest.MediaUri);
	if (media == null) {
		using(new SecurityDisabler()) {
			media = MediaManager.GetMedia(mediaRequest.MediaUri);
		}
		string text;
		if (media == null) {
			text = Sitecore.Configuration.Settings.ItemNotFoundUrl;
		}
		else {
			Assert.IsNotNull(Context.Site, "site");
			text = ((Context.Site.LoginPage != string.Empty) 
                        ? Context.Site.LoginPage: Sitecore.Configuration.Settings.NoAccessUrl);
		}
		//Setup redirect url - Start
		UrlString urlString = new UrlString(text);
		if (string.IsNullOrEmpty(urlString["returnUrl"])) {
			urlString["returnUrl"] = WebUtil.GetRawUrl();
			urlString.Parameters.Remove("item");
			urlString.Parameters.Remove("user");
			urlString.Parameters.Remove("site");
		}
		//Setup redirect url - End
		WebUtil.Redirect(urlString.ToString(), false);

		return true;
	}
	return this.DoProcessRequest(context, mediaRequest, media);
  }
In the web.config, <handler> tag has to be updated with new class and assembly name. 
<add verb="*" path="sitecore_media.ashx" type="CustomHandler.MediaRequestHandler, CustomHandler" 
name="Sitecore.MediaRequestHandler" />

Sitecore generate dynamic URL

When we migrate a site from legacy platform to Sitecore, there may be cases where Sitecore Rich Text Editor will have links. These html content with links will have relative URL and it may break if we move the page to different folder in Sitecore. 

Let's say we have the below HTML content. In order to set the links with dynamic URL, we need to read the HTML content (via HtmlaAgilityPack), find the links, generate the dynamic URL and save it.
<p>Lorem Ipsum has been the industry's standard dummy text ever since the 1500s. It has survived not only five 
<a title="centuries" href="/about-us/centuries">centuries</a>, but also the leap into electronic typesetting, 
remaining essentially unchanged.</p>
To generate the dynamic url, we can use the below method. These dynamic URLs will be rendered with friendly URL by Sitecore. 

For Sitecore Item:
LinkUrlOptions options = new LinkUrlOptions();
var dynamicUrl = LinkManager.GetDynamicUrl(item, options);
For Media Item:
var dynamicMediaUrl = MediaManager.GetMediaUrl(item, MediaUrlOptions.GetShellOptions());
Output:
<a title="centuries" href="~/link.aspx?_id=33B86674A94E4F2BA8B4576E606AFB45&amp;_z=z">centuries</a>
<a title="Image" href="-/media/dba85a49980e4e33916acbf798ce21fc.ashx">Image</a>

03 April, 2017

Sitecore - Get fallback language in code

Language Fallback in Sitecore is a key feature for multilingual website. Sitecore does the job to get the fallback version and languages for us. 

If you want to get the Fallback Language object, one of the way is below.
var fallbackLanguage = Sitecore.Data.Managers.LanguageFallbackManager.GetFallbackLanguage(
                            Sitecore.Context.Language, 
                            Sitecore.Context.Database);
blockquote { margin: 0; } blockquote p { padding: 15px; background: #eee; border-radius: 5px; } blockquote p::before { content: '\201C'; } blockquote p::after { content: '\201D'; }