Introduction
The series of articles introduces an innovative architecture to develop business web forms in enterprise software development which has better performance, higher productivity, more configurability and easier maintainability than traditional either ASP.NET or MVC development. This is the second article in the series for the solution. Before going forward, you shall take a look at the first article for the concept and overview at <<RapidWebDevUI Overview>>. The article is to introduce how "query" works and how to configure a query panel in a web form.
How "query" Works
The development for a query panel is composed of XML configuration and implementation to the method Query of interface IDynamicPage
as the following code snippet:
<QueryPanel HeaderText="Query Users">
<TextBox FieldName="UserName" Label="UserName: " />
<TextBox FieldName="DisplayName" Label="DisplayName: " />
<CheckBoxGroup FieldName="Membership.IsApproved"
FieldValueType="System.Boolean" Label="Approved: " Occupation="1">
<Item Text="Yes" Value="true" Checked="true" />
<Item Text="No" Value="false" />
</CheckBoxGroup>
</QueryPanel>
QueryResults Query(QueryParameter parameter);
RapidWebDev UI framework renders UI of query panel based on the filters configured inner of XML element QueryPanel
. The default supported query filter control types are CheckBox
, CheckBoxGroup
, ComboBox
, Date
, DateTime
, Integer
, Decimal
, TextBox
and RaduiGroup
. When all these controls do not meet your requirement, you can use XML element Custom
to configure your developed query filter control which follows the specification of a custom query filter control. As the above query panel configuration, the rendered UI is as the following screenshot:
When RapidWebDev UI framework renders UI of query panel, there is JavaScript manager instance for the query panel registered into web browser which manages all query filters including their status and values. When button Query is clicked, the query panel manager instance collects user input for each query filter and assembles an asynchronous HTTP request sending to RapidWebDev data service of dynamic page for JSON data response, seeing as ~/ObjectId/DynamicPageDataService.svc. I use Fiddler2 to track the HTTP request and response as the following screenshot. The response data with 4 returned records is only 2.5KB.
Finally, the query panel manager renders the JSON data into grid.
Query Panel XML Configuration
The default supported query filter control types mentioned above have common attributes as Label
, FieldName
, Operator
, FieldValueType
and Occupation
.
Label
is the label of the query filter in UI, E.G. "User Name:". The Label
supports variable markup like $VariableName$
or "$Namespace.ClassName.StaticPropertyName, AssemblyName$
". VariableName
shall be setup through the method SetupContextTempVariables
of interface IDynamicPage
.
FieldName
is used for the framework to assemble query expression by implementation of IPredicateCompiler
(namespace: RapidWebDev.UI.DynamicPages
) automatically. It supports properties of the associated object. E.G. we configure a dynamic page to manage users that the main entry of the page is User
. The entity User
references Membership
. And we want to query users through properties of Membership
like Membership.IsApproved
in the above code snippet. Linq2SQL predicate compiler (class: RapidWebDev.UI.DynamicPages.Linq2SQLPredicateCompiler
) compiles the query filter to expression as:
var query = from user in dataContext.Users
where user.Membership.IsApproved
select user;
Operator
is operator of query criteria which supports Equal
, StartsWith
, Like
, In
, NotIn
, GreaterThan
, GreaterEqualThan
, LessThan
, LessEqualThan
and Between
. By default, the framework chooses operator depends on the query filter control type.
FieldValueType
is the CLR type of parameter value of query expression. If FieldValueType
is specified, the query filter control value will be implicitly converted into the target type when assemble query expression.
Occupation
indicates how many cells the query filter control occupies in rendered query panel. E.G. the query panel layout implementation TableXColumnsQueryPanelLayout
renders all query filters in HTML table
. Occupation
means how many columns are occupied for the query filter control.
Besides these common attributes, you'd better to take a look at DynamicPage.xsd
for extended attributes of each query filter control.
Query Implementation
RapidWebDev data service of dynamic page converts asynchronous query request to QueryParameter
which includes query and sort information. QueryParameter
can be converted to query and sort expression by the implementation of interface IPredicateCompiler
(namespace: RapidWebDev.UI.DynamicPages
) which is configured in Spring.NET IoC. As the following implementation to query products, we only need to convert and concat the compiled query and sort expression with Linq2SQL lambda expression. And don't need to assemble query expression explicitly. So we can handle the requirement change on query filters easily without compilation. And the returned QueryResults(int recordCount, IEnumerable results)
is serialized to JSON data automatically by the framework.
public override QueryResults Query(QueryParameter parameter)
{
using (ProductManagementDataContext ctx =
DataContextFactory.Create<ProductManagementDataContext>())
{
IQueryable<Product> q = from p in ctx.Products
where p.ApplicationId ==
authenticationContext.ApplicationId
select p;
LinqPredicate predicate = parameter.Expressions.Compile();
if (predicate != null && !string.IsNullOrEmpty(predicate.Expression))
q = q.Where(predicate.Expression, predicate.Parameters);
if (parameter.SortExpression != null)
q = q.OrderBy(parameter.SortExpression.Compile());
int recordCount = q.Count();
var results = q.Skip(parameter.PageIndex * parameter.PageSize)
.Take(parameter.PageSize).ToList();
return new QueryResults(recordCount, );
}
}
Dynamic Data
We may have the requirement needs dynamic support which cannot be configured in XML like, render different query filters to users with different permission, or the items of a combobox in query panel should be rendered from database. RapidWebDev does support such scenarios. The dynamic page XML configuration can be configured a callback to change the configuration before UI rendering, seeing Page
/@ProcessCallbackType
in DynamicPage.xsd
. We can change the configuration at runtime in the callback. Besides, we can configure DynamicDataSource
for a combobox query filter. DynamicDataSource
is configured to pull items from a JSON driven external web service as the following code snippet. So in the example, when a user selects or inputs text into the editable combobox
, the combobox
refreshes the matching items from the external service.
<ComboBox FieldName="ParentHierarchyDataId" Label="Parent: " Editable="true"
MinChars="2" FieldValueType="System.Guid" ForceSelection="true">
<DynamicDataSource Url=
"/Services/HierarchyService.svc/json/FindByKeyword?limit=999"
Method="GET" TextField="Name" ValueField="Id" QueryParam="q">
<Param Name="hierarchyType" Value="$HierarchyType$" />
</DynamicDataSource>
</ComboBox>
Query Panel Layout
Interface IQueryPanelLayout
is used to render layout of query panel. RapidWebDev implements a html table
based layout as RapidWebDev.UI.DynamicPages.TableXColumnsQueryPanelLayout
by version 1.51. If you have an alternative requirement, you can implement a new strategy and configure to Spring.NET IoC instead of current TableXColumnsQueryPanelLayout
in RapidWebDev.Web\Spring\ui.config.
What's RapidWebDev
Website: http://www.rapidwebdev.org
RapidWebDev is an infrastructure that helps engineers to develop enterprise software solutions in Microsoft .NET easily and productively. It consists of an extendable and maintainable web system architecture with a suite of generic business model, APIs and services as fundamental functionalities needed in development for almost all business solutions. So when engineers develop solutions in RapidWebDev, they can have a lot of reusable and ready things then they can focus more on business logic implementation. In practice, we can save more than 50% time on developing a high quality and performance business solution than traditional ASP.NET development.
Related Topics