Saturday, April 16, 2016

Sitecore PageExtenders: non greedy approach

   There is great Sitecore feature: Page Extenders. It allows you to insert any HTML code to your pages. However inaccurate usage of it can harm your site.
   
    Once I installed Federated Experience Manager on Sitecore 7.2 I was unable to get it worked. For some reasons JavaScript on its pages failed. After deeper investigation I found that on any FxM request to server I got incorrect JSON. It was well formed, but at the end string
<input name="SC_ANALYTICS_PAGE" type="hidden" id="SC_ANALYTICS_PAGE" value="ecbb31a2-4c43-494d-88a1-811994213a89" /> 
was added. I figured out that this string was added by SBOS Accelerator module that was installed few days before. Reason of adding this string was greedy PageExеnder. It added this string everywhere, except few sites(shell, modules_shell). Such behavior also break some admin pages, e.g.: ShowConfig.aspx.

   After fixing this problem I can make conclusion: that in general it is much more better to specify where PageExtender should insert controls rather than specify where it should not insert controls. Even if you add a lot of exceptions, you could not cover by your exceptions everything that could appear in custom solutions. 

Wednesday, April 6, 2016

Sitecore Social Connected 2.1: Second Life

     After installation of Sitecore Social Connected 2.1 on Sitecore 7.2 following this reference (with few unusual steps for modules) I found out that I am not able to add Facebook and Twitter accounts. It was not a problem of this module. It was caused by changes in these social networks APIs. Trying to google solution I found it for Twitter. It was pretty easy, just replace one assembly with another.
   
    Error, that is appeared in log:
ERROR Value was either too large or too small for an Int32.
Exception: System.OverflowException
Message: Value was either too large or too small for an Int32.
Source: mscorlib
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
   at System.Convert.ToInt32(String value)
   at TweetSharp.TwitterService.GetAccessToken(OAuthRequestToken requestToken, String verifier)
   at Sitecore.Social.Twitter.Networks.Providers.TwitterProvider.AuthGetAccessToken(AuthArgs args)
   at Sitecore.Social.Client.Connector.SocialLogin.ProcessRequest(HttpContext httpContext)

   Could be fixed in 2 steps:
  1. Downloading newer Social Connected 3.0 module
  2. Unzipping and replacing TweetSharp.dll in your Sitecore
   I tried to find some similar solution for error with Facebook API:
"Invalid Scopes: offline_access, publish_stream, read_stream. This message is only shown to developers. Users of your app will ignore these permissions if present. Please read documentation for valid permissions at https://developers.facebook.com/docs/facebook-login/permissions".
But there was no ready to use solution. Problem was inside:

private void AddPermissionsToRequest(GetAccountCredentialsRequest accountCredentialsRequest, string networkName)
{
 string a;
 if ((a = networkName.ToLowerInvariant()) != null)
 {
  if (a == "facebook")
  {
   accountCredentialsRequest.Permissions.Add("offline_access", string.Empty);
   accountCredentialsRequest.Permissions.Add("publish_stream", string.Empty);
   accountCredentialsRequest.Permissions.Add("manage_pages", string.Empty);
   accountCredentialsRequest.Permissions.Add("read_stream", string.Empty);
   return;
  }
...

Ok, it is only constants, lets change them:

  1. Open ILDASM
  2. Dump Sitecore.Social.Client, Version=2.1.0.0 to some.il file
  3. Replace "offline_access", "publish_stream", "read_stream" with "publish_pages", "user_posts", "public_profile". It is not strict correspondence, it should be deeply investigated, but these permissions will be enough to create and post social messages.
  4. Using ILASM, assemble some.il into Sitecore.Social.Client and copy it to our Sitecore bin folder
But after trying to add Facebook account we get new error message:

ERROR The given key was not present in the dictionary.
Exception: System.Collections.Generic.KeyNotFoundException
Message: The given key was not present in the dictionary.
Source: mscorlib
   at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at Sitecore.Social.Facebook.Networks.Providers.FacebookProvider.GetDisplayName(Account account)
   at Sitecore.Social.Facebook.Client.Wizards.AddNetworkAccount.PageControls.FacebookWaitForAuthPageControl.GetFacebookAccount(Application application, String accessTokenSecret)
   at Sitecore.Social.Facebook.Client.Wizards.AddNetworkAccount.PageControls.FacebookWaitForAuthPageControl.GetAccountDisplayName()
   at Sitecore.Social.Client.Wizards.AddNetworkAccount.PageControls.WaitForAuthPageControl.CheckAuthStatus()

   After investigation I figured out that problem is inside:

public string GetDisplayName(Account account)
{
 System.Collections.Generic.IDictionary<string, object> accountData = this.GetAccountData(account, "/me");
 if (accountData == null)
 {
  return null;
 }
 return string.Format("{0} {1}", accountData["first_name"], accountData["last_name"]);
}

   Now Facebook returns only "name" instead of "first_name" and "last_name" separately. Guess, how we will solve this problem? Following similar steps that we have for previous fix we get new version of Sitecore.Social.Facebook.dll assembly. After copying it to Sitecore bin folder we are able to add Facebook account, create and publish posts with it.

Yahoo! We gave Sitecore Social Connected 2.1 second life.

P.S. Probably it is not all problems that could appear with changes in Facebook and Twitter APIs, but described above method fixes at least part of them. Use this solution on your own risk!


Friday, April 24, 2015

Debugging optimized managed code in Sitecore (any other website) / Disable JIT Optimization

Latest Sitecore installation contains assemblies build with checked optimization flag. It causes troubles when you attach to w3wp(IIS) process and try to debug them. There is known way how to disable JIT Optimization:

Disabling Runtime Optimization:

  1. Close any application that may be using the optimized binaries.
  2. Navigate to the folder containing the binaries.
  3. Create a new file named BINARYNAME_WITHOUT_THE_EXTENSION.ini
    E.g. If I do not want MyApp.exe to be optimized, and then create an INI file named MyApp.ini.
    E.g. If I do not want MyAppHelper.dll to be optimized, and then create an INI file named MyAppHelper.ini.
  4. Open the INI file.
    Add the following text:
    [.NET Framework Debugging Control]
    GenerateTrackingInfo=1
    AllowOptimize=0
  5. Save the file.
  6. Now you are ready to debug the application with optimization disabled.
  7. Note that you will have to create the INI file for each dll/exe that contains the code you want to debug.
  8. So the best way to go about this is to create a small windows app that will create an INI file for all files (exe and dll) in a particular folder.

But it does not work when you attach to w3wp process… It happens because IIS uses assemblies from ASP.Net Temporary folder, e.g. C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files. So, you should open your solution from folder on IIS and start debug from VS.

There are a lot of DLL files in Sitecore BIN folder and I decided to write powershell script that will create ini files for all assemblies.

Get-ChildItem (Get-Item -Path ".\" -Verbose).FullName -Filter *.dll | 
Foreach-Object{
$newName = $_.DirectoryName +"
\"+ [System.IO.Path]::GetFileNameWithoutExtension($_) + ".ini"
"
[.NET Framework Debugging Control]
GenerateTrackingInfo=1
AllowOptimize=0" | Out-File $newName
Write-host $newName
}

Use and enjoy :-)

Wednesday, January 14, 2015

Sitecore 8 Roles Dependencies

Here is Sitecore 8 roles graph with installed ExM and WFFM:

SitecoreRolesGraph8

Some remarks:

1) New roles: List Manager Editors, Experience Explorer, Analytics Advanced Testing, Sitecore Client Bucket Mangement, Analytics Maintaining

Monday, January 12, 2015

Sitecore Roles Graph

 

Here is visualization of Sitecore Roles Graph for Sitecore 7.2:

SitecoreRolesGraph

Wednesday, November 12, 2014

Sitecore Latest Log File in One Click

When you are working with Sitecore as developer or quality engineer, you often need to look at log files. There are few ways to do it: you can open files from your Data\Logs\ folder, you can use Log Viewer, you can use Log4Net Dashboard or even you can use any application that works with Log4Net. But for all this situations you need to do many clicks. That is why I decided to write Google Chrome extension that allows to get latest log file in browser in one click.

Google Chrome has limitations for extensions, for example you are not able to read from disk. But you can use some workarounds, for example NPAPI Plugins. It makes some limitation on extension, you can’t upload it to Chrome Web Store and you should install it as unpacked extension.

But it is not problem at all, it just makes installation of extension longer.

Here are steps that you should do:

1) Download extension folder from GitHub.

2) Visit chrome://extensions in your browser (or open up the Chrome menu by clicking the icon to the far right of the Omnibox:  The menu's icon is three horizontal bars.. and select Extensions under the Tools menu to get to the same place).

3) Ensure that the Developer mode checkbox in the top right-hand corner is checked.

4) Click Load unpacked extension… to pop up a file-selection dialog.

5) Navigate to the directory in which you downloaded files from step 1, and select it.

Enjoy getting latest log file in one click!

Screenshot 2014-11-12 15.59.31

Also you are able to configure wwwroot folder where your Sitecore environments live:

Screenshot 2014-11-12 16.02.00

P.S. Bonus: extension also works in Opera, however I do not know who uses Opera for development or testing.

Sunday, October 5, 2014

Sitecore MVC: Globalization for Model Attributes

There is an ability to create fields, fields labels and fields validation basing on model attributes in ASP.Net MVC:

public class SampleModel
{
[StringLength(50)]
[Required(AllowEmptyStrings = false)]
[DisplayName("Test")]
public object Name { get; set; }
}

In this case while you creating page you can use helpers:

@Html.LabelFor(m => m.Name)
@Html.TextBoxFor(m => m.Name)
@Html.ValidationMessageFor(m => m.Name)

You will get HTML form:



Everything will work with Sitecore MVC. However if you need provide translation of labels and messages on you form in Sitecore way you need to customize model attributes.


For DisplayNameAttribute it is easy to achieve with inheriting from standard attribute with adding Translate.Text:

public class DisplayNameAttribute : System.ComponentModel.DisplayNameAttribute
{
public DisplayNameAttribute(string displayName)
: base(displayName)
{
}


public override string DisplayName
{
get
{
return Translate.Text(base.DisplayName);
}
}
}

In this case when you will use new attribute for you model you will receive translated text for your labels. Same thing could be done for ValidationMessageFor, Required and other attributes.