Active Query Builder support area

Getting started with AQB 3 ASP.NET Edition in MVC 3+ and client-side JavaScript rendering

Last modified:


Important:

This guide is only for the classic ASP.NET MVC3+ with client-side JavaScript rendering!

Please refer to the appropriate guides for other environments:

 

Lots of demo projects illustrating various aspects of the functionality and different usage scenarios are shipped within the trial installation package. They can also be downloaded from the Active Query Builder 3 ASP.NET Examples GitHub repositories.

 

Note: if you use the previous major version in your projects, read the Migration Guide first.

 

Follow the steps below to embed Active Query Builder ASP.NET Edition to your project. 

Prerequisites

Add the ActiveQueryBuilder.Web.MVC NuGet package to your project OR add references to the following assemblies:

  • \assemblies\ActiveQueryBuilder.Core.dll
  • \assemblies\ActiveQueryBuilder.Web.Server.dll
  • \third-party\Newtonsoft.Json.dll

Active Query Builder requires Newtonsoft.Json assembly version 6.0 or higher. You can get it by installing the Newtonsoft.Json NuGet package or download it directly from the Newtonsoft JSON website.

You may also need to add one or more assemblies to get connected to your database(s) to retrieve metadata from it, e.g.:

  • \assemblies\ActiveQueryBuilder.OLEDBMetadataProvider.dll

The whole list of supported database connectivity packages and appropriate connectors can be found here.

Is it necessary to set the CopyLocal property of "ActiveQueryBuilder.*" assemblies to True.

 

Embedding Visual Query Builder

  1. Render the following HTML markup on your web page with JavaScript:

    @model ActiveQueryBuilder.Web.Server.QueryBuilder
    @{
        ViewBag.Title = "Simple Client Rendering Demo";
    }
    
    <div class="col-md-12">
        <div id="qb"></div>
        <div class="qb-ui-layout">
            <div class="qb-ui-layout__top">
                <div class="qb-ui-layout__left">
                    <div id="treeview"></div>
                </div>
                <div class="qb-ui-layout__right">
                    <div id="navbar"></div>
                    <div id="canvas"></div>
                    <div id="statusbar"></div>
                    <div id="grid"></div>
                </div>
            </div>
            <div class="qb-ui-layout__bottom">
                <div id="sql"></div>
            </div>
        </div>
    </div>
    
    @section scripts
    {
        <script src="aqb_client.js"></script>
    
        <script>
            // identifies query builder instance in the session; must be the same on the server side
            var qbId = 'SimpleClient';
    
            $(function () {
                AQB.Web.UI.QueryBuilder(
                    qbId,  // instance identifier
                    $('#qb'),  // id or path to HTML DOM element
                    { reinitUrl: // path to the session reinitialization method
                        '/QueryBuilder/CreateQueryBuilder' } 
                );
                AQB.Web.UI.ObjectTreeView(qbId, $('#treeview'));
                AQB.Web.UI.SubQueryNavigationBar(qbId, $('#navbar'));
                AQB.Web.UI.Canvas(qbId, $('#canvas'));
                AQB.Web.UI.StatusBar(qbId, $('#statusbar'));
                AQB.Web.UI.Grid(qbId, $('#grid'));
                AQB.Web.UI.SqlEditor(qbId, $('#sql'));
    
                AQB.Web.UI.startApplication(qbId);
            });
        </script>
    }

    The reinitUrl constructor parameter is needed for the case a component instance is destroyed on the server due to the client's inactivity.

    Alternatives: You can initialize the component on the server-side later if the query builder UI is not shown right on the page load. In this case, you need to specify the second parameter to the startApplication method. This can be either
    a) a path to the component's new instance creation method on the server (example), or
    b) a function that fires a request to create the component and handles errors (example).

     

  2. Initialize an instance of the QueryBuilder object in the action method of your controller. While creating a new instance of it, initialize the MetadataProvider and SyntaxProvider properties with proper objects. Define a proper database connection object as a source for the MetadataProvider or load metadata from the XML file.

    public class SimpleOledbDemoController : Controller
    {
        // Professional version feature: if you want to let the user simultaneously 
        // build several queries, you must assign different instance ids to them.
        // In the Standard version, this parameter is ignored.
        private string instanceId = "SimpleClient";
    
        public ActionResult Index()
        {
            CreateQueryBuilder();
            return View();
        }
    
        private QueryBuilder CreateQueryBuilder()
        {
            // Get an instance of the QueryBuilder object
            var qb = QueryBuilderStore.Get(instanceId);
    
            if (qb != null)
                return qb;
    
            // Create an instance of the QueryBuilder object
            qb = QueryBuilderStore.Create(instanceId);
    
            // Turn this property on to suppress parsing error messages when user types a non-SELECT statement.
            qb.BehaviorOptions.AllowSleepMode = false;
    
            // Assign an instance of the syntax provider which defines SQL syntax and metadata retrieval rules.
            qb.SyntaxProvider = new MSAccessSyntaxProvider();
    
            // ==== The 1st way: ==================================
            // Bind Active Query Builder to a live database connection.
            qb.MetadataProvider = new OLEDBMetadataProvider
            {
                // Assign an instance of DBConnection object to the Connection property.
                // In this demo: create a new instance of OLEDBConnection for the "Northwind.mdb" MS Access database.
                Connection = new OleDbConnection(
                    "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\Northwind.mdb;Persist Security Info=False;") 
            };
    
            // ==== The 2nd way: ==================================
            // Load MetaData from the pre-generated XML file.
    
            // Denies metadata loading requests during the work session.
            qb.MetadataLoadingOptions.OfflineMode = true;
    
            qb.MetadataContainer.ImportFromXML(pathToYourXMLFile);
            // ====================================================
    
            // Assign the initial SQL query text the user sees on the _first_ page load
            qb.SQL = @"Select o.Order_ID, c.ID As a1, c.First_Name, s.ID
                    From Orders o Inner Join
                        Customers c On o.Customer_ID = c.ID Inner Join
                        Shippers s On s.ID = o.Shipper_ID
                    Where o.Ship_City = 'A'";
                   
            return qb;
        }
    }

    Alternative: You can automate the initialization of the QueryBuilder object (syntax and metadata providers, database connection or metadata loading from the XML file) via the special section of the "web.config" file. This way is useful when you want to run the backend in a Docker container. Learn the details in this article.

     

Embedding Criteria Builder in your data browsing UI

The QueryTransformer component and the accompanying CriteriaBuilder visual control let build a full-featured user interface to browse query result data. Note that Active Query Builder doesn't provide any means to display data as there are plenty of free and paid controls that can cope better with this task. Active Query Builder can be easily integrated with most of these controls providing the flexibility you need.

Please read the QueryTransformer and CriteriaBuilder guides for details.

  1. Render the CriteriaBuilder control on the page. You can place it on the same page with the QueryBuilder control or on a separate page.

    <div id="cb"></div>
    
    @section scripts
    {
        <script src="aqb_client.js"></script>
    
        <script>
            // identifies the query builder instance in the session; must be the same on the server side
            var qbId = 'SimpleClient';
    
            $(function () {
                AQB.Web.UI.CriteriaBuilder(qbId, $('#cb'));
    
                AQB.Web.UI.startApplication(qbId);
            });
        </script>
    }

     

  2. Add the following initialization code to the ActionResult controller method:

        private string instanceId = "SimpleClient";
    
        public ActionResult Index()
        {
            var qb = CreateQueryBuilder(); // see the previous code sample for the implementation
    
            CreateQueryTransformer(qb.SQLQuery); 
    
            return View();
        }
    
        private QueryTransformer CreateQueryTransformer(SQLQuery query)
        {
            // Get an instance of the QueryTransformer object
            var qt = _aqts.Get(instanceId)
            
            if (qt != null)
                return qt;
    
            // Create an instance of the QueryTransformer object
            qt = _aqts.Create(instanceId);
     
            qt.QueryProvider = query;
            qt.AlwaysExpandColumnsInQuery = true;
            
            return qt;
        }

     

  3. Handle CriteriaBuilder events to integrate it with your data grid:

            $(function () {
                AQB.Web.onCriteriaBuilderReady(subscribeToChanges);
            });
            
            function subscribeToChanges(cb) {
                createGrid(); // user proc to create or initialize grid
    
                cb.on(cb.Events.AfterSyncCriteriaBuilder, function () {
                      updateGridColumns(cb.columns); // user proc to update list of query columns
                      updateGridData(); // user proc to update grid data
                });
    
                cb.loadColumns(); // trigger the initial query columns loading
    
                // request data from the server when the user changes the filter
                cb.on(cb.Events.CriteriaBuilderChanged,
                    function () {
                        onCriteriaBuilderChanged(cb, updateGridData); 
                    });
            }
            
            function onCriteriaBuilderChanged(cb, callback) {
    
                // check if there aren't any incomplete conditions in the CriteriaBuilder
                if (cb.isValid()) {
                
                    // send the control state to the server to update the query
                    cb.transformSql(function () { 
                        callback(); // a callback to use (usually run) the transformed query
                    });
                } 
            }

     

  4. The updateGridData procedure should perform the AJAX request to the server which will execute the query read from the QueryTransformer.SQL property and return data to the client. Make sure to properly handle SQL query execution errors.

  5. You can also let users change sorting, apply grouping and aggregations, calculate totals, and paginate the resultset in your data browsing UI using the QueryTransformer API.

See the Query Results demo project for details (included in the installation package and available on GitHub).

 

What to read next?

 


Is this article helpful for you?