PJAX is a jQuery plugin that uses AJAX and pushState to deliver a fast browsing experience with real permalinks, page titles, and a working back button. It is available to download from GitHub.

In all websites, the header and footer remain the same for all pages. Only the page contents (the content in the middle area between the header and footer) are changed for each page. PJAX uses this concept to fetch only the page contents while the header and footer remains the same for each page. In short, you can also say PJAX is the brother of the Update Panel of Web Forms that works for ASP.NET Core.

With PJAX, you get the following advantages.

    The website becomes fast since the header and footer are not loaded for different pages.
    You website behaves like a SPA (Single Page Application), and you don’t need to employ Angular framework in your ASP.NET Core Application.
    If you have worked with Update Panel of ASP.NET Web Forms then it is quite similar to it.

This is how PJAX will work.
See the below video which illustrates the working of PJAX.

PJAX Implementation in ASP.NET Core

Integration of PJAX in ASP.NET Core involves the following things.

Layout.cshtml View
In your application _Layout.cshml View, add jQuery and PJAX script links. You do this inside the head section:
    <script src="https://code.jquery.com/jquery-2.2.4.js"></script> 
    <script src="~/js/jquery.pjax.js"></script> 
    Also call PJAX on all anchors inside the #main element.  
    <script type="text/javascript"> 
        $(function () { 
            // call pjax 
            $(document).pjax('#menu li a', '#main', { timeout: 10000 }); 
     
        }); 
    </script> 


Loading Image
If you want to show the loading image when a new page contents are being fetched then add the following code inside the script section of Layout:
    $(document).ajaxStart(function () { 
        $("#loadingDiv").show(); 
    }); 
     
    $(document).ajaxComplete(function (event, jqxhr, settings) { 
        $("#loadingDiv").hide(); 
    }); 


Also, place the loading image somewhere in your layout.
    <div id="loadingDiv" style="display:none;"> 
        <img src="~/loading.gif" /> 
    </div> 


Do not worry as the source code contains all the loading image codes. Do check it.

Add some links to your _Layout.cshtml View. On these links, PJAX will work so when these links are clicked then their page’s contents are loaded by PJAX (but the header and footer area are not loaded).
    <ul> 
        <li><a href="/Home/Index">Index</a></li> 
        <li><a href="/Home/About">About</a></li> 
        <li><a href="/Home/Contact">Contact</a></li> 
    </ul> 


Don’t forget to add the #main element on the Layout so that PJAX only fetches the contents inside this #main element with AJAX.
    <div id="main"> 
        @RenderBody()  
    </div> 

Controller
Add a controller called Home with the following 3 action methods:

    public IActionResult Index() 
    { 
        if (string.IsNullOrEmpty(Request.Headers["X-PJAX"])) 
            return View(); 
        else 
            return PartialView("/Views/Home/Index.cshtml"); 
    } 
     
    public IActionResult About() 
    { 
        if (string.IsNullOrEmpty(Request.Headers["X-PJAX"])) 
            return View(); 
        else 
            return PartialView("/Views/Home/About.cshtml"); 
    } 
     
    public IActionResult Contact() 
    { 
        if (string.IsNullOrEmpty(Request.Headers["X-PJAX"])) 
            return View(); 
        else 
            return PartialView("/Views/Home/Contact.cshtml"); 
    }  


Make sure that the Action methods that are called by PJAX (i.e. clicking on menu links in my case) return PartialViews. Since PJAX sends ‘X-PJAX’ request in the HTTP Header therefore I can easily make a selection of View or Partial View by checking the HTTP header.

The condition applied in each action method that does this work is:
    if (string.IsNullOrEmpty(Request.Headers["X-PJAX"])) 
        return View(); 
    else 
        return PartialView("/Views/Home/Index.cshtml");  


Views

Add the 3 Views called ‘Index.cshtml’, ‘About.cshtml’ and ‘Contact.cshtml’ inside the ‘Views/Home’ folder:

Index.cshtml
    <div class="templatemo_content_area"> 
        <h1>WELCOME TO Index Page</h1> 
    </div> 


About.cshtml
    <div class="templatemo_content_area"> 
        <h1>WELCOME TO About Page</h1> 
    </div> 


Contact.cshtml
    <div class="templatemo_content_area"> 
        <h1>WELCOME TO Contact Page</h1> 
    </div> 


Also add _ViewStart.cshtml View inside the ‘Views’ folder:
    @{ 
        Layout = "_Layout"; 
    }