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

Wednesday, August 17, 2016

Hail, Architect- Don't just get swayed by the hype around new releases of Sitecore.

It's not just about sitecore or it's new releases or update which is announced to all out there. Its about plan it and time it well. Your stakeholder is dependent upon you. What you say is written on the stone. So be careful. Like all other releases of software or product there is cooling period for any product to get matured and get adopted to the ecosystem. What I meant is a time to make your product stand strong against all issues which may surface in production and can haunt you for a week. If you see in the past almost all product or software underwent changes due to fixes or unstable or may be success to certain degree or call it a flop show.

Having said this, cooling period is something one must consider while setting up expectation with stakeholder. Watch the space carefully. 

Just don't get swayed by the hype of features it comes with rather you face the reality with risk/issues the new release can offer in return.

Next time you hear something about releases with new feature .Hold your horses! 

Assess it well! Act Smart ! Sell while Deliver !


This is my opinion and may not concur with everyone.



Tuesday, August 16, 2016

How to get to the bottom of Sitecore Performance issues?

The idea is to give the quicklinks to gather data for performance issue analysis. Most of us may not be aware about the intrinsic .net framework and internal of CLR in details as we more focus on implementations and make use of features. This is where actual concept comes into play.


Debugging TOOL

1. DebugDiag

https://channel9.msdn.com/Shows/Defrag-Tools/Defrag-Tools-122-DebugDiag-Part-2
Performance counters
Proc Dump

2. Debugging Production Environment Windbg & SOS

https://channel9.msdn.com/Series/-NET-Debugging-Stater-Kit-for-the-Production-Environment/Windbg--SOS-03

3. Sons of Strike- SOS.dll

https://msdn.microsoft.com/en-us/library/bb190764(v=vs.110).aspx

If you really want to deep dive further refer Tezz Fernandez blogs and articles.

A long story short, if you are into critical production performance issue, sitecore support team may need your help to get certain process stats and data here are the few links that you must go through to nail down the issues.
https://blogs.msdn.microsoft.com/tess/

Some unanswered Questions?

Q.1  How to collect memory dumps using Task Manager ?
https://kb.sitecore.net/articles/758511

Q.2. How to collect memory dumps using ProcDump ?
https://kb.sitecore.net/articles/253710

Q.3. How to identify Sitecore process in Performance Monitor ?
https://kb.sitecore.net/articles/931689

Q.3. How to collect memory dumps using Managed GC Aware Dump ?
https://kb.sitecore.net/articles/284285

Q.4. How to collect memory dumps ?
https://kb.sitecore.net/articles/488758

Deep Containment Designs

var location = default(string);
if (vendor != null)
{
    if (vendor.ContactPerson != null)
    {
        if (vendor.ContactPerson.HomeAddress != null)
        {
            location = vendor.ContactPerson.HomeAddress.LineOne;
        }
    }
}

Now, using C# 6, this same idiom becomes much more readable:

var location = vendor?.ContactPerson?.HomeAddress?.LineOne;







Tuesday, August 9, 2016

Sitecore Database Internal -Items, VersionedFields and UnVersionedFields

These tables pretty much make sitecore CMS. Items and values stored in fields. Everything is just an ITEM.


SELECT [Id]
      ,[ItemId]
      ,[Language]
      ,[FieldId]
      ,[Value]
      ,[Created]
      ,[Updated]
      ,[DAC_Index]
  FROM [Sitecore_master].[dbo].[UnversionedFields]

SELECT [Id]
      ,[ItemId]
      ,[Language]
      ,[Version]
      ,[FieldId]
      ,[Value]
      ,[Created]
      ,[Updated]
      ,[DAC_Index]
  FROM [Sitecore_master].[dbo].[VersionedFields]

SELECT [ID]
      ,[Name]
      ,[TemplateID]
      ,[MasterID]
      ,[ParentID]
      ,[Created]
      ,[Updated]
      ,[DAC_Index]
  FROM [Sitecore_master].[dbo].[Items]

Monday, August 8, 2016

Capture Asp.net webservice traffic request when using with sitecore

I was doing bit of research playing around postman interceptor and fiddler but couldn't find the solution to view the calls made by sitecore.net to asp.net webservice that is been called as part of middle tier.

Even Redgate Ant profiler even could not able to capture such outgoing requests to other asp.net webservice. The idea was to assess the response time elapsed to get data from external webservice to our sitecore solution. We want to make sure what we developed in sitecore will be as optimum in terms of our design approach. We ensured most of the component is cached and rendered appropriately.

  • Doing this you can see performance profiling stats of outgoing request to external api , web service, wcf service etc.
  • You can see them available in Redgate Ants performance profiler and VS2015 n tier profiling.
  • Fiddler to give you all in and out of http requests.
 
Finally i was surfing through knowledge base of sitecore and happen to find this work around.
Note: The profiler will only capture requests made by System.Net.HttpWebRequest

Courtesy Sitecore
https://kb.sitecore.net/articles/017181



Solution






To configure the Fiddler tool to capture web service calls from an ASP.NET web site, you need to perform the following actions on your solution:
  1. In the Global.asax file, implement the following Application_Start method:
        public void Application_Start()
        {
            ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; });
        }
    
  2. In the Global.asax file, add the following import statements:
    <%@ Import Namespace="System.Net" %>
    <%@ Import Namespace="System.Net.Security" %>
  3. In the web.config file, configure the following XML under the section:
    <system .net>
      <defaultproxy enabled="true" usedefaultcredentials="true">
        <proxy autodetect="false" bypassonlocal="false" proxyaddress="http://127.0.0.1:8888" usesystemdefault="false">
      </proxy>

</configuration>


  • Enable Fiddler to capture the HTTPS traffic.

  • After the traffic is captured by Fiddler, it can be saved for further sharing and analysis.