ASP.NET Web Layer

Blake Niemyjski edited this page Aug 19, 2015 · 2 revisions

Web Library

What is the Web Library?

The NetTiers Web Library is a set of Controls and Objects that provide powerful tools to make your web development projects with NetTiers much easier and more efficient.

Typed DataSource Controls -vs- EntityDataSource

The Web Library offers both Strongly Typed DataSource Controls as well as the more generic EntityDataSource.

The strongly typed DataSource controls are great because by binding to them you have all your object's properties and methods pre-defined and at your disposal. All of this shows up in IntelliSense. These maintain the ObjectDataSource controls event model, except they are geared to your data, relationships, and domain.

On the other hand, the EntityDataSource control is a generic datasource and is useful because it uses 100% reflection to work with the data providers. This is great when you need to change the type at runtime, or maybe you have written your own methods within the DataAccessLayer that you would like to call, then you would simply use the EntityDataSource control.

User Interface controls

The Web Library adds a collection of user interface controls to your toolbox such as the strongly bound repeaters, EntityGridView, EntityDropDownList (and bound field version), BoundRadioButtonField, HyperlinkField, EntityLabel and a GridViewSearchPanel.

Web.Config Configuration

To use the NetTiers Web Library you'll need to add a connection string...

<configuration>
  <connectionStrings>
    <add name="Northwind.Data.ConnectionString" connectionString="..." />
  </connectionStrings>
</configuration>

and register web controls...

<configuration>
  <system.web>
    <pages>
      <controls>
        <!-- register web controls for use on all pages -->
        <add tagPrefix="data" namespace="Northwind.Web.Data" assembly="Northwind.Web"/>
        <add tagPrefix="data" namespace="Northwind.Web.UI" assembly="Northwind.Web"/>
      </controls>
    </pages>
  </system.web>
</configuration>

and configure a transaction manager...

<configuration>
  <system.web>
    <httpModules>
      <!--
        Enable transaction-per-request pattern;  
        This module allows a single TransactionManager to be shared by
        all data access operations executed during a page request.  
        Used by the EntityDataSource control when
        the EntityDataSource.EnableTransaction property is set to True.
      -->
      <add name="EntityTransactionModule" 
            type="Northwind.Web.Data.EntityTransactionModule, Northwind.Web"/>
    </httpModules>
  </system.web>
</configuration>

and add a config section...

<configuration>
  <configSections>
    <section name="Northwind.Data" type="Northwind.Data.Bases.NetTiersServiceSection, 
      Northwind.Data" allowDefinition="MachineToApplication" 
      restartOnExternalChanges="true" />
  </configSections>
  <Northwind.Data defaultProvider="SqlNetTiersProvider">
    <providers>
      <add
        name="SqlNetTiersProvider"
        type="Northwind.Data.SqlClient.SqlNetTiersProvider, Northwind.Data.SqlClient"
        connectionStringName="Northwind.Data.ConnectionString"
        providerInvariantName="System.Data.SqlClient"
        entityFactoryType="Northwind.Entities.EntityFactory"
        useEntityFactory="true"
        enableEntityTracking="true"
        enableMethodAuthorization="false"
        useStoredProcedure="false"
        defaultCommandTimeout="30"/>
    </providers>
  </Northwind.Data>
</configuration>

That's it.

And yes, by the way, don't forget to add references to your Data, Entities, and Web projects, by right clicking on your web project / web site and selecting 'Add Reference'.

Using the Typed DataSource Controls

Strongly Typed DataSource controls: You will find that just by typing <data: you will see a list of your DataSource controls ready to be used to get ahold of your data. These maintain the ObjectDataSource controls event model, except they are geared to your data, relationships, and domain.

Intellisense

Productivity Enabler When you select the SelectMethod Attribute, you will see via intellisense a list of all available methods from your domain. How cool is that!

Intellisense

Simple WebForm Example: Here's an example of a simple webform in it's minimilist form, that would display a grid of all Employees with Auto-Generated columns.

Web Form

Design View: Taking the form and selecting only the columns that I want, we create a nice grid.

Design View

Data View Results:

Here's the result of of the form. The wonderful part of the Typed DataSource control is that you don't have to do anything when you want to edit/insert/delete an object. You simply have the grid call the Edit/Delete/Insert command, which can be done a variety of ways in ASP.net 2.0.

Design View

Edit

After Edit

TypedDataSource w/ Microsoft AJAX Example

GridView Paging, Sorting and inline Update/Delete

After Edit

Creating the Grid

First, create a new page and add the following GridView control:

NOTE: It's very important that you specify the DataKeyNames property of the Gridview, otherwise, Insert/Update/Delete will not work.

<asp:GridView ID="GridView1" AutoGenerateColumns="false" runat="server"
       DataSourceID="CustomersDataSource1" 
       DataKeyNames="CustomerID"   
       PageSize="10" AllowPaging="true" AllowSorting="true">
   <Columns>
      <asp:CommandField ShowEditButton="True" />
      <asp:BoundField DataField="CustomerID" HeaderText="Cust #" SortExpression="CustomerID" />
      <asp:BoundField DataField="CompanyName" 
            HeaderText="Company" SortExpression="CompanyName" />
      <asp:BoundField DataField="ContactTitle" HeaderText="Title" SortExpression="ContactTitle" />
      <asp:BoundField DataField="ContactName" HeaderText="Name" 
            SortExpression="ContactName" />
      <asp:BoundField DataField="City" HeaderText="City" SortExpression="City" />
      <asp:BoundField DataField="Region" HeaderText="Region" SortExpression="Region" />
      <asp:BoundField DataField="PostalCode" HeaderText="Postal Code" 
            SortExpression="PostalCode" />
      <asp:BoundField DataField="Country" HeaderText="Country" SortExpression="Country" />
      <asp:CommandField ShowDeleteButton="true" />
   </Columns>
</asp:GridView>

Next, add the CustomersDataSource control to your page:
This is the tough part, so strap it in!!!

<data:CustomersDataSource ID="CustomersDataSource1" 
   runat="server"
   SelectMethod="GetPaged" 
   EnablePaging="true" 
   EnableSorting="true"/>

Umm... That's it!

And you should have a functional GridView with paging and sorting!

Using Microsoft AJAX: Now here comes the fun part, AJAXifying (see dictionary) your grid. As you know Microsoft released an extremely useful AJAX library called Micrsoft AJAX. Additionally, Microsoft created a toolkit filled with all sorts of useful AJAX tools called the AJAX Toolkit and released it to the community as open source.

More information can be found: http://ajax.asp.net

Demonstrating Microsoft AJAX with .netTiers

Now we want to add a filter to our page to demonstrate a new feature to NetTiers:

<table border="0" width="310" style="margin-bottom:10px;">
<tr>
   <td>
      <asp:Label ID="CountryLabel" 
            AssociatedControlID="CountryList" runat="server" Text="Country:" />
   </td>
   <td>
      <asp:DropDownList ID="CountryList" AutoPostBack="true" runat="server">
            <asp:ListItem Value="">All</asp:ListItem>
            <asp:ListItem>Brazil</asp:ListItem>
            <asp:ListItem>Canada</asp:ListItem>
            <asp:ListItem>France</asp:ListItem>
            <asp:ListItem>Germany</asp:ListItem>
            <asp:ListItem>Italy</asp:ListItem>
            <asp:ListItem>Mexico</asp:ListItem>
            <asp:ListItem>Spain</asp:ListItem>
            <asp:ListItem>UK</asp:ListItem>
            <asp:ListItem>USA</asp:ListItem>
            <asp:ListItem>Venezuela</asp:ListItem>
      </asp:DropDownList>
   </td>
   <td align="right">
      <asp:Label ID="TimeLabel" runat="server" Font-Names="Verdana" Font-Size="10px">
            <%= DateTime.Now %/></asp:Label>
   </td>
</tr>
</table>

Next, change the data source control above to add a parameter for the whereClause parameter of the GetPaged method. The SqlParameter allows you to define external filter controls that will be combined to generate the filter expression:

<data:CustomersDataSource ID="CustomersDataSource1" runat="server"
   SelectMethod="GetPaged" EnablePaging="true" EnableSorting="true">
   <Parameters>
      <data:SqlParameter Name="WhereClause" UseParameterizedFilters="false">
         <Filters>
            <data:CustomersFilter Column="Country" ControlID="CountryList" />
         </Filters>
      </data:SqlParameter>
   </Parameters>
</data:CustomersDataSource>

AJAX Magic: Now we can add the magic! Make sure you have a reference to the AJAX Script Manager:

<atlas:ScriptManager ID="ScriptManager1" EnablePartialRendering="true" runat="server" />

We want to wrap the GridView control with an UpdatePanel:

<asp:UpdatePanel ID="GridPanel" UpdateMode="Conditional" runat="server">
   <ContentTemplate>

      <!-- GridView declaration goes here -->

   </ContentTemplate>
   <Triggers>
      <atlas:ControlEventTrigger ControlID="CountryList" EventName="SelectedIndexChanged" />
   </Triggers>
</asp:UpdatePanel>

Notice that the trigger is tied to the CountryList control so that the GridView is updated every time the selected country is changed. Poof!!! All Done.

Using the EntityDataSource Control

The EntityDataSource controls is useful because it uses 100% reflection to work with the data providers. This is great when you need to change the type at runtime, or maybe you have written your own methods within the DataAccessLayer that you would like to call. You would simply use the EntityDataSource control.

<data:EntityDataSource ID="dataSourceID" runat="server"
   TypeName="Namespace.Data.DataRepository, Namespace.Data"
   TypeProperty=""
   ProviderName=""
   EntityTypeName=""
   EntityKeyTypeName="System.Guid"
   EntityKeyName=""
   SelectMethod="GetAll"
   InsertMethod="Insert"
   UpdateMethod="Update"
   DeleteMethod="Delete"
   EnablePaging="false"
   EnableSorting="false"
   EnableTransaction="true"
   InsertDateTimeNames=""
   UpdateDateTimeNames=""
   Filter=""
   Sort=""

   OnSelecting=""
   OnSelected=""
   OnInserting=""
   OnInserted=""
   OnUpdating=""
   OnUpdated=""
   OnDeleting=""
   OnDeleted=""
>
   <Parameters>
   </Parameters>
</data:EntityDataSource>
  • ProviderName (required) - an alias for TypeProperty; the name of the static property of the DataRepository class which returns a reference to the specific provider instance. ex: ProviderName="CustomersProvider" for Northwind.Data.DataRepository.CustomersProvider
  • EntityTypeName (required) - the fully qualified class name of the entity class that is handled by the specified data provider.
  • EntityKeyName - the name of the property that holds the primary key value.
  • EntityKeyTypeName - the fully qualified class name for the return type of the EntityKeyName property.
  • EnableTransaction - set to True if the EntityDataSource should rely on the EntityTransactionModule class to supply a TransactionManager object.
  • InsertDateTimeNames - a comma-separated list of DateTime property names to initialize to the current DateTime.Now value during an insert operation.
  • UpdateDateTimeNames - a comma-separated list of DateTime property names to initialize to the current DateTime.Now value during an update operation.
  • Filter - the value to apply to the ListBase.Filter property after a select operation (only if EnablePaging is false)
  • Sort - the value of the parameter to pass to the ListBase.Sort(string) method after a select operation (only if EnableSorting is false)

Example: This is an example of populating a DropDownList control with data retrieved using the EntityDataSource control.

<asp:Label ID="ShipViaLabel" runat="server" Text="Ship Via" AssociatedControlID="ShipViaList" />

<asp:DropDownList ID="ShipViaList" runat="server"
    SelectedValue='<%# Bind("ShipVia") %>'
    AppendDataBoundItems="True"
    DataSourceID="ShippersDataSource"
    DataTextField="CompanyName"
    DataValueField="ShipperID"
>
    <!-- an empty ListItem along with the AppendDataBoundItems property allow for a nullable relationship -->
    <asp:ListItem Value="" Text="" />
</asp:DropDownList>

<data:EntityDataSource ID="ShippersDataSource" runat="server"
    ProviderName="ShippersProvider"
    EntityTypeName="Northwind.BLL.Shippers, Northwind.BLL"
    EntityKeyTypeName="System.Int32"
    SelectMethod="GetAll"
    Sort="CompanyName ASC"
/>  

Using Many To Many Relationship Controls The ManyToManyListRelationship control manages the junction table that links your primary entity with a foreign key table. Please see highlighted code below.

<asp:FormView ID="FormView1" runat="server" DataSourceID="CustomersDataSource" DefaultMode="Edit">
    <EditItemTemplate>
        <table border="0">
        <tr>
            <td>Cust #:</td>
            <td><asp:Label ID="CustomerIDLabel" runat="server" Text='<%# Bind("CustomerID") %>' /></td>
        </tr>
        <tr>
            <td>Company Name:</td>
            <td><asp:TextBox ID="CompanyNameTextBox" runat="server" Text='<%# Bind("CompanyName") %>' /></td>
        </tr>
        <tr>
            <td valign="top">Demographics:</td>
            <td>
                <!-- the visual representation of the many-to-many relationship -->
                <asp:CheckBoxList ID="CustomerDemographicsList" runat="server"
                    DataSourceID="CustomerDemographicsDataSource"
                    DataTextField="CustomerDesc"
                    DataValueField="CustomerTypeID"
                />
                
                <!-- provides the list of available data for the relationship -->
                <data:EntityDataSource ID="CustomerDemographicsDataSource" runat="server"
                    ProviderName="CustomerDemographicsProvider"
                    EntityTypeName="Northwind.BLL.CustomerDemographics, Northwind.BLL"
                    SelectMethod="GetAll"
                    Filter="CustomerDesc != 'Temporary'"
                    Sort="CustomerDesc ASC"
                />
                
                <!-- provides management of the link table -->
                <data:EntityDataSource ID="CustomerCustomerDemoDataSource" runat="server"
                    ProviderName="CustomerCustomerDemoProvider"
                    EntityTypeName="Northwind.BLL.CustomerCustomerDemo, Northwind.BLL"
                    EntityKeyTypeName="System.String"
                    SelectMethod="GetByCustomerID"
                >
                    <Parameters>
                        <asp:QueryStringParameter Name="EntityId" QueryStringField="id" />
                    </Parameters>
                </data:EntityDataSource>
                
                <!--
                    The relationship controls hook one or more EntityDataSource controls to the 
                    EntityDataSource specified by the PrimaryMember.EntityDataSourceID property.
                    This allows multiple insert/update operations to be executed during a single
                    form submission.
                -->
                <data:ManyToManyListRelationship ID="CustomerCustomerDemoRelationship"                                         runat="server">
                    <%-- represents the Customers table --%>
                    <PrimaryMember runat="server"
                        DataSourceID="CustomersDataSource"
                        EntityKeyName="CustomerID"
                    />
                    <%-- represents the CustomerCustomerDemo link table --%>
                    <LinkMember runat="server"
                        DataSourceID="CustomerCustomerDemoDataSource"
                        EntityKeyName="CustomerID"
                        ForeignKeyName="CustomerTypeID"
                    />
                    <%-- represents the CustomerDemographics table --%>
                    <ReferenceMember runat="server"
                        DataSourceID="CustomerDemographicsDataSource"
                        ListControlID="CustomerDemographicsList"
                        EntityKeyName="CustomerTypeID"
                    />
                </data:ManyToManyListRelationship>
            </td>
        </tr>
        </table>
    </EditItemTemplate>
    
    <FooterTemplate>
        <asp:Button ID="UpdateButton" runat="server" CausesValidation="True" CommandName="Update" Text="Update" />
        <asp:Button ID="CancelButton" runat="server" CausesValidation="False" CommandName="Cancel" Text="Cancel" />
    </FooterTemplate>
</asp:FormView>

<!-- primary entity data source -->
<data:EntityDataSource ID="CustomersDataSource" runat="server"
    ProviderName="CustomersProvider"
    EntityTypeName="Northwind.BLL.Customers, Northwind.BLL"
    EntityKeyTypeName="System.String"
    EntityKeyName="CustomerID"
    SelectMethod="GetByCustomerID"
>
    <Parameters>
        <asp:QueryStringParameter Name="EntityId" QueryStringField="id" Type="String" />
    </Parameters>
</data:EntityDataSource> 

Relationship Views

The EntityDropDownList and associated BoundEntityDropDownField

EntityDropDownList - Derives from a DropDownList, but adds a few extra features such as the ability to add a null item (adds a child ListItem), make it readonly(converts it to a label), make the control required (uses a RequiredFieldValidator) and it supports type ahead (javascript).

example use:

<data:EntityDropDownList runat="server" ID="myfieldDDL" 
    DataSourceID="productsDataSource"  
    DataTextField="ProductName" 
    DataValueField="ProductID"
    AppendNullItem="true" 
    NullItemText="<select a value>"
    Required="true"
    ReadOnly="false"
    FriendlyName="My drop down field"
    ErrorText="*"
    RequiredErrorMessage="This drop down is required"
    CaseSensitiveKeySort="true"
    SelectedValue='<%# Bind("ProductID") %>' />

BoundEntityDropDownField - As above but derived from BoundField so that it can be used within a grid (EntityGridView). It caches the data so that it is only read once for all the bound rows.

example use:

<data:EntityGridView runat="server" ID="gridView"
    DataSourceID="productsDataSource"
    DataKeyNames="ProductID" 
    AutoGenerateColumns="false" 
    AutoGenerateEditButton="true" 
    AllowPaging="true" 
    AllowSorting="true">
    <Columns>
        <asp:BoundField DataField="ProductID" HeaderText="Product ID"
            ReadOnly="True"  SortExpression="ProductID" />
        <asp:BoundField DataField="ProductName" HeaderText="Product Name"
            SortExpression="ProductName" />
        <data:BoundEntityDropDownField DataField="SupplierID" HeaderText="Supplier"
            SortExpression="SupplierID" 
            DataSourceID="suppliersDataSource" 
            DataTextField="CompanyName" 
            DataValueField="SupplierID" 
            AppendNullItem="true" />
        <data:BoundEntityDropDownField 
            DataField="CategoryID" 
            HeaderText="Category"
            SortExpression="CategoryID" 
            DataSourceID="categoriesDataSource" 
            DataTextField="CategoryName" 
            DataValueField="CategoryID" 
            AppendNullItem="true" />
    </Columns>
</data:EntityGridView>    
<data:ProductsDataSource runat="server" ID="productsDataSource" sort="ProductName"  
    EnableSorting="true" EnablePaging="true" SelectMethod="GetPaged" />
<data:CategoriesDataSource runat="server" ID="categoriesDataSource" Sort="CategoryName" />
<data:SuppliersDataSource runat="server" ID="suppliersDataSource" Sort="CompanyName" />
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.