Tuesday, March 21, 2017

Sitecore Active Directory:SitecoreADMembershipProvider Initialize and add provider at runtime in application_start

Key : Know and how

These are the following set of queries may be asked once we able to roll out , design or implement sitecore ldap module.

  • Whether Membership, role or profile provider required. Choose wisely, if membership is required just use that. 
  • The project requirement might be to use sitecore custom or out box role so active directory ldap role might not be worth to include.
  • Ensure you don't allow admin to action delete , edit of active directory users from sitecore. This may have implications. The rational: There could be service account or group created for content author and administrator user will be different from centralized security team. Let one team handle the removal of users from active directory server rather handle through sitecore.(Ensure you give read only permission to service account that is created in active directory server) This will allow one direction add and delete of users. This will help avoid accidental deletion from sitecore.
  • Understand Role and profile provider does not support SSL whereas membership support SSL only when it is trusted and known. (Need to explore more.) Therefore sometimes port 636 will not accept ssl certificate however sign and seal options are available with port 389 check ConnectionProtection attribute of LightLdap SitecoreAdMembership membership provider., the LDAPS connection should use a certificate which is properly validated by a Root CA:
  • This should be validated as per environment ‘sign-and-seal’ only works if the client (Web App VM) is on the same domain as the Server (AD Domain Controller) .Check below article web post by microsoft.
  • Consider credentials to be stored in key vault for azure environment. Downside the ldap membership provider of sitecore stores it in custom configuration unlike connectionstring or appsettings. For this to overcome you have to configure and initialize the sitecore membership provider at runtime in Application_start. I have given some reference code block to help you get around this.

https://social.technet.microsoft.com/wiki/contents/articles/2980.ldap-over-ssl-ldaps-certificate.aspx


Anton Jason, Has helped me with below solution reference. Later it helped me integrate this further.



Remember to add reference LightLdap.dll

public class ApplicationStartup
{
      
        public static void Startup()
        {
           
        }

        public virtual void Process(object args)
        {          
                SitecoreADMembershipProvider provider = new SitecoreADMembershipProvider();
                NameValueCollection config = new NameValueCollection();
                SitecoreADMembershipProvider provider = new SitecoreADMembershipProvider();
                 NameValueCollection config = new NameValueCollection();
                 // Configure your provider here. 
                 config["type"] = "LightLDAP.SitecoreADMembershipProvider";
                 config["name"] = "SomeProviderName";
 
                 config["connectionStringName"] = "LDAPConnString";
                 config["applicationName"] = "sitecore";
 
                 config["connectionUsername"] = ConfigurationManager.AppSettings["AppSettingKeys-UserName"];
                 config["connectionPassword"] = ConfigurationManager.AppSettings["AppSettingKeys-Password"];
 
                 config["minRequiredPasswordLength"] = "1";
                 config["minRequiredNonalphanumericCharacters"] = "0";
                 config["requiresQuestionAndAnswer"] = "false";
 
                 config["requiresUniqueEmail"] = "false";
                 config["connectionProtection"] = "secure";
 
                 config["attributeMapUsername"] = "sAMAccountName";
                 config["enableSearchMethods"] = "true";
 
                 config["customFilter"] = "(memberOf=Your org custom filter)";
 
                 provider.Initialize("SomeProviderName", config);
                 provider.AddTo(Membership.Providers);
        }
}

I used jetbrains dotpeek to look into sitecore LightLdap and it helped me understand how sitecore has created a custom wrapper
to implement its membership, role and profile.

Remember one thing there is struct MembershipProviderSettings which has all the above configuration defined.
This is protected if you planning to extend create custom class and inherit SitecoreADMembership provider. This is the only way out.


namespace LightLDAP
{
  public class SitecoreADMembershipProvider : MembershipProvider
  {
    protected bool initialized;
    protected MembershipProviderSettings settings;
    protected PartialDataSource source;

    public override string ApplicationName { get; set; }


    public SitecoreADMembershipProvider()
      : this((IAdMembershipProvider) new AdMembershipProvider())
    {
    }

    public SitecoreADMembershipProvider(IAdMembershipProvider innerProvider)
    {
      this.InnerProvider = innerProvider;
      this.settings = new MembershipProviderSettings();
    }

    public override void Initialize(string name, NameValueCollection config)
    {
      try
      {
        this.ApplicationName = config["applicationName"];
        this.settings.Initialize(config);
        config.Remove("serverPageTimeLimit");
        config.Remove("useNotification");
        try
        {
          bool isInnerFailed = false;
          try
          {
            this.InnerProvider.Initialize(name, config);
          }
          catch (Exception ex)
          {
            isInnerFailed = true;
          }
          try
          {
            this.settings.InitializeHidden(this.InnerProvider, isInnerFailed);
            this.source = DataStorageContainer.GetPartialSource(this.settings.AdsPath, this.settings.UserName, this.settings.Password, this.settings.AttributeMapUsername, this.settings.UseNotification);
            this.initialized = true;
          }
          catch (Exception ex)
          {
          }
          base.Initialize(name, config);
        }
        catch (Exception ex)
        {
          Log.Error("The AD membership provider couldn't be initialized: " + ex.Message, ex, (object) this);
        }
      }
      catch (Exception ex)
      {
        Log.Error("AD:", ex, (object) this);
        throw;
      }
    }
  }
}

Thursday, March 16, 2017

Sitecore Active Directory 1.3 Bug Reported: ProviderStatus throws error Unable to cast object of type 'Sitecore.Support.Security.SwitchingMembershipProvider' to type 'Sitecore.Security.SwitchingMembershipProvider'.

When you installed and setup Sitecore Active directory module 1.3 for update 8.2.1 it will throw below error. We reported this bug with sitecore support and they came up with required fix.


https://kb.sitecore.net/articles/520134

Tuesday, March 14, 2017

Sitecore Best Practice Avoid using sitecore intrinsic Controller name and action

Conflict with Sitecore Controller name: Multiple controller with same name

Avoid using AuthenticationController, HomeController and something more relevant to sitecore.

https://community.sitecore.net/developers/f/8/t/1634

This is the case when you are done with your development and you have enough time to check the event , iis and sitecore logs to cleanup your solution to meet good code and performance bench mark. Do consider this check before you come to this stage of clean-up. This will save time. I understand its cloud and such error doesn't matter. However its good to have less warnings in your logs. This will help you drill down to most critical error in production defects.

Having said that , scrutinize your logs during development using sitecore  log viewer or analyzer.


Monday, February 27, 2017

Sitecore Aligned Azure Cheat sheet

Access KUDU Service 

https://somewebsitename-staging.scm.azureservices.abc.com.au

Access File System- App Service Editor

https://somewebsitename-staging.scm.azureservices.abc.com.au/dev/wwwroot

Azure Key Vault

This required to safe guard important configuration key value pair.

https://docs.microsoft.com/en-us/azure/key-vault/key-vault-whatis

Azure Resource Explorer

https://azure.microsoft.com/en-au/blog/azure-resource-explorer-a-new-tool-to-discover-the-azure-api/
You can indeed explorer whole lot of stuff in here. This is very handy if you want to troubleshoot api end points or look for any details related to app service for any instance such as microsoft.web where you can lookup instance details.


Sitecore Azure Diagnostics

https://marketplace.sitecore.net/Modules/Sitecore_Azure_Diagnostics.aspx

Sitecore Azure Blob storage logging

Features:
• Append regular, WebDAV, Search, Crawling and Publishing Sitecore diagnostics
• Based on Azure Blob Storage
• Append Blobs are used to store diagnostics as a text data
• Text data is compatible with Sitecore Log Analyzer tool
• Support multiple Web Apps instances
• Clean up out-of-date blobs using Sitecore Agent
• Support Sitecore Log Viewer application to open, download and deleted blobs.

Azure Storage Append Log

https://blogs.msdn.microsoft.com/windowsazurestorage/2015/04/13/introducing-azure-storage-append-blob/

Sitecore Azure Application Insights

https://doc.sitecore.net/sitecore_experience_platform/setting_up_and_maintaining/sitecore_on_azure/analytics/analyze_sitecore_logs_with_application_insights


https://mwenhao.wordpress.com/2017/02/06/ehh-where-is-my-sitecore-azure-log/



Change Logging Timestamp: Azure Timezone Offset setting

To locate your local timezone to overwrite default time.
http://www.louischarlesgagnon.com/post/azure-app-service-set-timezone-for-your-web-application


Advanced Azure Web apps Sitecore debugging and troubleshooting

https://kb.sitecore.net/articles/111669









This article reviews tools and methods to collect information to use for troubleshooting a Sitecore XP application on Azure Web Apps.
The following sections describe ways to gather relevant data for typical performance issues, such as:
  • High CPU usage.
  • Memory leaks.
  • Long response time and other types of slowness.
  • -------------------------------------------------------------------------------
  • Collecting a memory dump Using Process Explorer (On-Demand) 
  • Collecting a memory dump using Procdump utility 
  • Collecting a memory dump using Diagnostics as a Service (DaaS) 
  • Collecting a performance profiling data

How to get a full memory dump in Azure App Services-Using KUDU

https://blogs.msdn.microsoft.com/jpsanders/2017/02/02/how-to-get-a-full-memory-dump-in-azure-app-services/

https://blogs.msdn.microsoft.com/benjaminperkins/2017/02/01/create-a-memory-dump-for-your-slow-performing-web-app/

About Full vs Mini Dump

Command Line for CMD-
d:\devtools\sysinternals\procdump -accepteula -ma 5484

This one is indeed interesting blog
https://blogs.msdn.microsoft.com/benjaminperkins/2017/02/01/create-a-memory-dump-for-your-slow-performing-web-app/

List down:
1. Method #1Using procdump.exe
2. Method #2 Using Diagnostics as a Service (DAAS)
3. Method #3 Using KUDU process explorer

Azure App Service: Generating memory dumps on first chance exception using Procdump

https://blogs.msdn.microsoft.com/kaushal/2017/05/08/azure-app-service-generating-memory-dumps-on-first-chance-exception-using-procdump/
D:\home\Dumps>procdump.exe -accepteula -ma -e 1 -f "System.UnauthorizedAccessException" 7808
Azure App Service instances include the sysinternals suite in the default image. They can be located here via the KUDU console:D:\devtools\sysinternals



Azure App Service: How to connect to the Kudu site of a specific instance


https://blogs.msdn.microsoft.com/kaushal/2016/11/21/azure-app-service-how-to-connect-to-the-kudu-site-of-a-specific-instance/


Azure Management Service: NEW ADMIN UI
 

https://channel9.msdn.com/Shows/Azure-Friday/Azure-API-Management-New-Admin-UI-and-Mocks

You can now mock api data without being backend ready. You can test api without using developer portal.
Swagger definition available as part of code editor.

Sitecore Quick Cheatsheet

Introduction 

Just want to keep log of quick stuff that can act as quick reference. This will be work in progress , I'll keep adding as an when I come across things like this.

Protect Sitecore Item

Hide Sitecore Item


Package Sitecore Roles & Users

You can package sitecore Roles and Users. Refer screenshot. Add roles and users.

Sunday, February 26, 2017

Sitecore.Net Performance Findings & Recommendation 1

WeformView vs RazorView

Glimpse.axd: Performance output. 

Findings: 

Each view rendered with two view engines:Razor & WebForm. 

Type

Redundant + Overhead processing

Recommendations: 

Switch off unnecessary view engine if not required.



References:

http://blog.getglimpse.com/
http://stackoverflow.com/questions/5912980/turning-off-the-webformviewengine-when-using-razor






Thursday, February 23, 2017

Preview Transform and Add Transform OOB Issue with other config type

Configuration Transformation: Evironment Configuration


XDT: Transform

In recent times I have been working sitecore configuration config transformation for different environment and I came across the scenario where Add transform and Preview is supported in Visual studio only for web.config files not for other configuration. To fix this I just install Slow Cheetah extension and restarted my visual studio with project solution , everything works fine.

https://marketplace.visualstudio.com/items?itemName=WillBuikMSFT.SlowCheetah-XMLTransforms


Sitecore config builder
https://marketplace.sitecore.net/Modules/S/Sitecore_Custom_Config_Builder.aspx?sc_lang=en
https://marketplace.sitecore.net/modules/sitecore_configbuilder.aspx

Saturday, December 10, 2016

Sitecore Item browser and technical doco viewer tool

Jumpstart

This module is available in Sitecore Market place and source code in git.

This tools saves time in creating and extracting sitecore item defination. This browser and viewer can be used for review, quick lookup and extract for technical documentation.
Support Prerequisites
  • Tested in Sitecore Xp
  • Worked well with sitecore mvc renderings. Not tested for components with sublayout

Work in progress
  • Root element such home is not displayed and view. Will be available in next release.
  • Must be installed only in development environment in CMS content authoring server or local 
  • Not suitable for CD or production or test env.

This module is about browsing and viewing sitecore item technical definition such as template, layout, device, presentation and fields definition for given sitecore item in content tree. This is very useful tool to extract content for technical document for any project. It gives all details of given item its template, base template, renderings, datasource and all. So all we need to do is to browse and extra the definition for our technical documentation. 
Once this package is installed ,you can browse item defination and details using below url.

  • http://website/sitecore/admin/browsedoco.aspx 
  • http://website/sitecore/admin/knowMe.aspx 

you can also find the source code available in  
https://github.com/poojarsn/MyDoco





Saturday, November 26, 2016

LINQ Performance pitfall instead a Pit stop!

I would rather named the title as Linq performance pit stop. Anyway in the interest of time, here is, one of the good examples of how we can start with something very trivial linq query to something convoluted one. Always remember the query in memory or on fly comes with its own pros and cons. One must understand how to use them and when. I took this particular example from pluralsight and thought it to be worth sharing.

Courtesy
https://app.pluralsight.com/library/courses/linq-more-effective/table-of-contents

by Mark Heath.

Slow
var longest=books.First(b => b.Pages==books.Max(a => a.Pages));

Better
var mostBooks= books.Max(a => a.Pages);
var longest=books.First(b => b.Pages == mostBooks);

Best
var longest= books.MaxBy(p => p.Pages);

Hope this useful.

SingleOrDefault() 
Check before using FirstOrDefault
This should be used if query returns single recordset.

var scalarDataSet= result?.Results?.SingleOrDefault();


Linq Data Parallelism
var quotes = quotesForAllProducts();//e.g Get quotes for all products
Parallel.ForEach(products, item => Process(item,quotes));
private void Process(Product item,List<Quote> quotes)       {           var quote= quotes?.SingleOrDefault                   (p =>                       p.Id.Trim().Equals(item.Id ?? string.Empty));           if (quote != null)           {               item.Cost = quote.TotalAmount.GetValueOrDefault();               item.Code = quote.Code;           }                  }

Parrallelism
System.Linq.ParallelEnumerable
Set object values for superset.
Packages = poducts.AsParallel().Select(p => new Package                 {                     tId = p.tId,                     vId = p.vId                 }).ToList(),

SelectMany
private void SetProductsSubSet(IList<Product> products)     {         _products= (IEnumerable<ProductDetail>) products?.AsParallel().SelectMany(a => a.subLevel.Select(p => new ProductDetail         {             Id = a.Id,             Type = a.Type,         })) ?? new List<ProductDetail>();       } 


DefaultIfEmpty() Left Join
public List<Product> AddHospitalAndExtrasProduct()        {            return                 (from A in Main                join B in SubB on A.ID equals B?.Id into MainAndSubB                    from ResultSetA in MainAndSubB.DefaultIfEmpty()                join B in SubC on A.ID equals C?.Id into MainAndSubC                    from ResultSetC in MainAndSubC.DefaultIfEmpty()
            select new Product             {                 Id = Main.Id,                 Name = Main.Name,                 SubBId = ResultSetA != null ? ResultSetA .SubBId : string.Empty,                 SubCId = ResultSetC != null ? ResultSetC .SubCId : string.Empty,             }).ToList();                   }


Wednesday, September 28, 2016

Check field Template Source value using sitecore powershell SPE

Use Case :Review

Suppose we have a custom rich text  and it has been sourced with custom component or css .This is added when developer creates template field in data template. The below code snippet can be used as part of your review and refactoring process to clean up sitecore items. 

Here is the quick pick..Check Source field of rich text is empy or null.

$targetTemplate    = Get-item 'master:/sitecore/templates/User Defined/Common/Data';
$templateFilter    = Get-Item "master:/sitecore/templates/System/Templates/Template Field";


Get-ChildItem $targetTemplate.FullPath -recurse 
| Where-Object { $_.TemplateName -eq $templateFilter.Name -and $_.type -eq 'Rich Text' -and $_["source"] -eq ''} 
| ForEach-Object {
    $_.Name
    $_.Type
    $_["Source"] 
}

Reference


http://sitecore.stackexchange.com/questions/203/unable-to-get-value-of-source-using-spe

Add base template using sitecore powershell extension

Use Case

It might happen you may have to add base template to all your user defined template. Below is the script to help doing this. I used Adam's code as reference to get this working. During development we could have reach to a stage where we end up with lot of user defined templates and at some point we review and refactor template to have uniform approach. One of the script below can come handy to save some of our refactoring time.

# Add base template programmatically


$targetTemplate    = Get-item 'master:/sitecore/templates/User Defined/Common/Data';
$templateFilter    = Get-Item "master:/sitecore/templates/System/Templates/Template";
$templateToBeAddAsBaseTemplate     = Get-Item 'master:/sitecore/templates/User Defined/Common/Data/Carousel'


Get-ChildItem $targetTemplate.FullPath -recurse | Where-Object { $_.TemplateName -eq $templateFilter.Name -and $_.Name -eq "promo"} | ForEach-Object {
    if(-not ($_."__Base template" -match "$($templateToBeAddAsBaseTemplate.Id)")){
           #If not exist then add
         $_."__Base template" = "$( $_."__Base template")|$($templateToBeAddAsBaseTemplate.Id)" 
    }
}

Reference

http://stackoverflow.com/questions/18990973/append-base-template-to-template-using-sitecore-powershell

Add base template using sitecore powershell extension

Use Case

It might happen you may have to add base template to all your user defined template. Below is the script to help doing this. I used Adam's code as reference to get this working. During development we could have reach to a stage where we end up with lot of user defined templates and at some point we review and refactor template to have uniform approach. One of the script below can come handy to save some of our refactoring time.



$targetTemplate    = Get-item 'master:/sitecore/templates/User Defined/Common/Data';
$templateFilter    = Get-Item "master:/sitecore/templates/System/Templates/Template";
$templateToBeAddAsBaseTemplate     = Get-Item 'master:/sitecore/templates/User Defined/Common/Data/Carousel'


Get-ChildItem $targetTemplate.FullPath -recurse | Where-Object { $_.TemplateName -eq $templateFilter.Name -and $_.Name -eq "promo"} | ForEach-Object {
    if(-not ($_."__Base template" -match "$($templateToBeAddAsBaseTemplate.Id)")){
           #If not exist then add
         $_."__Base template" = "$( $_."__Base template")|$($templateToBeAddAsBaseTemplate.Id)" 
    }
}

Reference

http://stackoverflow.com/questions/18990973/append-base-template-to-template-using-sitecore-powershell

Monday, September 12, 2016

Sitecore CMS Active Directory Module and LDAP integration.

Introduction

I'm not going to reinvent the wheel. The idea is to help fellow developer to troubleshoot and few show stoppers that can come as a problem during integration of ldap to sitecore AD Module. I just try to put my experience altogether so as to address some issues and useful tool that can help you get started.

Use Cases

Enabling LDAP authentication in content authoring aka CMS system will provide additional level of security access control in place. This will ensure limited access and no misuse even we have CMS -CA accessible only to internal network non accessible publicly.

Assumption:

You've LDAP /AD account in place. Say. There is dev, test and prod group account created in AD. To each of these group set of AD users are assigned. Each of these group must be assigned with Service account say sv_dev_user.and so on. The Service account act as primary source of authentication to allow any external system seek access to AD group. Later it will enable set of users to access application or system.

  • Development/Test/Production Environment
    • AD GROUP 
      • AD User(s) 
      • One Service Account
Note : The service account is one that is used by sitecore AD Module.

This is used by one of the sitecore configuration.
add name="customAD" type="LightLDAP.SitecoreADMembershipProvider" connectionStringName="LDAPConnString" applicationName="sitecore" minRequiredPasswordLength="1" minRequiredNonalphanumericCharacters="0" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
connectionUsername="[Enter SERVICE Account User Name]" connectionPassword="[Enter Password]" connectionProtection="Secure" attributeMapUsername="sAMAccountName" enableSearchMethods="true"

***Facts About:AD Service Account Vs AD User Account

In certain scenarios we have systems running under AD Credentials (i.e. under a Service Account). These Service Accounts are created in exactly the same way as user accounts; the only difference being the name and description. A few things have been done to make a distinction between the two account types (e.g. which OU the account is in, whether "password never expires" is enabled, if "service account" is in the description), but there's no one rule which can be applied to everything to clearly distinguish between the two.

How to get Started?

Follow this blog , this more precise and easy steps to start with.

Troubleshooting?  

1. OU Group wrongly used in LDAP Connection string?

Always look at the right form of LDAP connection string. 99% of the cases Ldap connection is wrongly used in terms of OU group. There may be nested OU group. The best way to figure out OU group is use LDAPAdmin.exe. Check download section.

Connect LdapAdmin with service account userId and pwd. Once connected to LDAPAdmin try to locate AD Group and take one member(user) of that group and check its property . You can easily find the right hierarchy of OU aswell as right OU group.

2. Check LDAP Port in Ldap connection string?

  • Port 389(used for ldap browsing) vs 636 (secure)
add name="LDAPConnString" connectionString="LDAP://Mydomain:389/OU=SomePrimaryOU,OU=SomeChildOU,DC=Mydomain,DC=myCompany,DC=com,DC=au"

3. Always verify connectivity of LDAP AD account from server

One way to check directly using ldapAdmin.exe or you can check through this simple code base.

using System.DirectoryServices;
 
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            //mycompany.com.au
            var entry = new DirectoryEntry(@"LDAP://yourdomain:636/OU=primary,OU=secondary,DC=yourdomain,DC=mycompany,DC=com,DC=au", "Active directory user name","password");

            var search = new DirectorySearcher(entry);
            SearchResult result = search.FindOne();  

      }
      }
}

4. Sitecore Provider Status

                                       http://mydemo/sitecore/admin/providerstatus.aspx


5. User Manager : AD User Import Status Successful!


6. Domain: Check CustomAD Domain appeared!


7. Role Manager: Assign Sitecore Role to User

Make sure Sitecore Client Role is assigned to AD users.


8. Finally Login with AD user account

Ensure you using the domain name that you added as one of the membership provider. say you got domain name mydomain and you have used membership provider as below. Then you should login with customAD\UserId

add name="customAD" type="LightLDAP.SitecoreADMembershipProvider" connectionStringName="LDAPConnString" applicationName="sitecore" 

Last but not the least

If you unable to get any lead. Enable debug mode to true in ldap.config

Open the /App_Config/Include/ldap.config file, locate the LDAP.Debug setting and set it to true.
This setting is set to false by default. When the changes to the pluggable .config file are applied immediately, the next request to the module will dump much more information to the Sitecore CMS log file.

Downloads

References

Azure Cloud

Friday, August 26, 2016

Sitecore MVC Session handling

It all started when we had session timeout and it resulted in error page. Yes session checks were not handled properly.All I was looking to solve this trivial problem with quick code fix but it turn out to be a bit of research again. This is indeed a sitecore world, where every request surface with filters, route and action. Each request is fragmented as we had controller rendering to serve all our dynamic data and transaction commits.

****Register Global Filter to check for session. 
This will not work as there are some workflow pages which are not session or authorization dependent. It bit the purpose.

Next thought of handling this in SessionEnd pipeline.
GlobalFilters.Filters.Add(new SessionExpireAttribute());

****SessionEnd Pipeline Response.Redirect and Server.Transfer will not work!

Session_End is fired internally by the server, based on an internal timer. And thus there is no HttpRequest associted when that happens. That is why Response.Redirect or Server.Transfer does not make sense and will not work. 

**** SessionEnd is not fired if session mode is outproc.
It will be fired only when using session mode set as inproc or Custom.

****Solution: Not elegant but it worked.
Let the session timeout and then eventually it will be send to the path of common error handling module where we can take appropriate action to redirect it to login page or some information page to notify user about session timeout.
 
****Post Session Timeout-  User action server side event.
****Post Session Timeout- User action cliend side event fired.(Check for IsAjaxRequest)
 public class RenderingControllerExceptionProcessor : ExceptionProcessor
{  
    public override void Process(ExceptionArgs args)
    {
            var userContext = SessionService.Get();
            if (userContext == null)
                if (args.ExceptionContext.HttpContext.Request.IsAjaxRequest())
                {
             //send something to response result.
                    args.ExceptionContext.Result = new JsonResult
                    {
                        Data = new
                        {
                            Error = "NotAuthorized",
                            LogOnUrl = "/login"
                        },
                        JsonRequestBehavior = JsonRequestBehavior.AllowGet
                    };
                }
                else
                {
                    WebUtil.RedirectToLoginPage();
                }
   }
}
OR
 private bool IsSessionExpired()
        {
            if (HttpContext.Current.Session != null)
            {
                
                if ( HttpContext.Current.Session.IsNewSession)
                {
                    //Note: Below code fails for Custom session.Works for Inproc
                    string cookieHeaders = HttpContext.Current.Request.Headers["Cookie"];

                    if ((null != cookieHeaders) &&
                       (cookieHeaders.IndexOf("ASP.NET_SessionId", StringComparison.Ordinal) >= 0))
                    
                        // IsNewSession is true, but session cookie exists,
                        // so, ASP.NET session is expired
                        return true;
                    
                }
                // Session is not expired and function will return false,
                // could be new session, or existing active session
                return false;
            }
            return false;
        }
The only solution is to handle through global application error event in sitecore rendering.


Always Consider these values when dealing with session:.

  1. Polling interval
  2. Compression
  3. Session type
  4. SlidingExpiration

Side Note:
If your worker process restarts and it causes your cache to clear, think of using agent to ping Keepalive.aspx.

Monday, August 22, 2016

How string Interpolation can simplify expression? No more string.format

Just this example 


Console.WriteLine($"When {condition} is true, {(condition ? "it's true!" : "It's False")}");

C# Simplify Dispose Object

public void RetireHenchman()
{
    var disposableMinion = Minion as IDisposable;
    if (disposableMinion != null)
        disposableMinion.Dispose();
    Minion = null;
}
 
The null coalescing operator can make this code more concise as well:
 
public void RetireHenchman()
{
    (Minion as IDisposable)?.Dispose();
    Minion = null;
}
 


Friday, August 19, 2016

MVC Filter Order

While dealing with MVC filters we got various options to tweak the flow of action method calls at local and global level of application execution, The best case scenario are as follows:-

1. Check authorization for each action call.
2. Check whether request is legitimate as if it is human or bot based
3. Check or validate model request
4. Check session timeout
5. Check request length

[Authorize]--AuthorizeAttribute


  • IsAuthorized
  • OnAuthorized

public class ProtectedApiAttribute : AuthorizeAttribute
    {
        public ProtectedApiAttribute()
        {
            // do nothing, _repository will be lazily instantiated
        }
 
 
        protected override bool IsAuthorized(HttpActionContext actionContext)
        {
            var methodAccess = string.Empty;
            if (actionContext.Request.Method == HttpMethod.Get) methodAccess = "Get";
            if (actionContext.Request.Method == HttpMethod.Post) methodAccess = "Post";
            if (actionContext.Request.Method == HttpMethod.Put) methodAccess = "Put";
            if (actionContext.Request.Method == HttpMethod.Delete) methodAccess = "Delete";
 
            var isAuthorised = false;
            if (HttpContext.Current.Session.Count > 0)
            {
                isAuthorised = true;
            }
            return isAuthorised;
        }
    }
}


Filters run in the following order:
  1. Authorization filters
  2. Action filters
  3. Response filters
  4. Exception filters
For example, authorization filters run first and exception filters run last. Within each filter type, the Order value specifies the run order. Within each filter type and order, the Scope enumeration value specifies the order for filters. This enumeration defines the following filter scope values (in the order in which they run):
  1. First
  2. Global
  3. Controller
  4. Action
  5. Last

Thursday, August 18, 2016

C# 6.0 Initialization Gotchas

class Program
    {
        static void Main(string[] args)
        {
           var container = new SomeContainer();
           var range = Enumerable.Range(0, 10);
           foreach (var item in range)
               container.SomeNumbersHasSolution.Add(item);
 
           Console.WriteLine(container.SomeNumbersHasSolution.Count);
 
           foreach (var item in range)
               container.SomeNumbersHasProblem.Add(item);
 
           Console.WriteLine(container.SomeNumbersHasProblem.Count);
 
           Console.Read();
       }
       public class SomeContainer
       {
           public IList SomeNumbersHasProblem => new List();
           public IList SomeNumbersHasSolution { get; } = new List();
 
       }



  • SomeNumberHasProblem---Result 0
  • SomeNumberHasSolution---Result 10