Apr 18 2006

Paging With ObjectDataSource in One Trip

Category: ASP.NET 2.0 - GeneralBil@l @ 11:55

This post assumes you have the previous post on the DataObjectTypeName and ObjectDataSource .

Usually, when we want to allow paging when we are using ObjectDataSource, we should enable paging in both the Data-Bound Control (GridView an example) and the ObjectDataSource.

  • GridView: AllowPaging and off course you need to set PageSize.
  • ObjectDataSource: EnablePaging, also you need to set the:
    • MaximumRowsParameterName="maxRows"
    • StartRowIndexParameterName="startRowIndex"
    • SelectCountMethod="RecordCount"

The method specified in the SelectMethod should now have 2 parameters:

  • int maxRows
  • int startRowIndex

The key point I wanted to show here is the following:

When you want to allow paging, you should add a method called SelectCountMethod, this method is used by the ObjectDataSource to know how many pages there will be.

An old conception for me has been that, we are doing two database round-trips. One to get the data and one to get the Record Count.

This is not true anymore!!! Why?

Let me explain, if the methods in the data mapper class are instance methods that is, not defined with static methods, then ODS will create an instance of the object specified in the TypeName, and access those methods, then disposes that instance.

However, if we had enabled paging, and both the SelectMethod and SelectCountMethod are both instance methods, then, the same instance will be used to access those two methods. So now, inside your Select method, you can get the count of the total records, and store it in a private instance, and then have a SelectCountMethod return that instance. This way, in one shot, you got both values, and since the "same instance" is created by the ODS, means you can for sure make use of the value of the record count, check this sample:

   [DataObjectMethodAttribute(DataObjectMethodType.Select, true)]
    public List<Employee> Get()
    {
        // your logic to retrieve all records

        // Get the Count record
        _CountRecords = (int)dr["Count"];

        return new List<Employee>();
    }

    public int RecordCount()
    {
        return _CountRecords;
    }

Hope this helps you,

Regards

Tags:

Apr 18 2006

DataObjectTypeName and ObjectDataSource

Category: ASP.NET 2.0 - GeneralBil@l @ 10:32

For most of you using the ObjectDataSource, you must have passed by DataObjectTypeName property of the ObjectDataSource.
I have been working with it for a while, but thought of sharing with you the beauty of that property.

Usually, ObjectDataSource uses two modes to pass parameters for the data mapper's methods:

  • Simple Data Types (string, int, etc ...)
  • Custom Objects (Input for methods would be an object)

When you set the DataOjectTypeName ="MyClass" of the ObjectDataSource, then the following should be valid:

  • All CRUD (Create, Retrieve, Update, Delete) methods specified in the TypeName property of ObjectDataSource should expect a parameter of type "MyClass" as an input parameter, except for the Retrieve method for sure. For instance:
    public static void Delete(MyClass p_Myclass)
    { }
  • The MyClass is a simple object, that has some public properties like: ID, Name, Email, etc ... Make sure that the properties' names match exactly witht the names of the fields displayed by the Data-Bound Controls. For instance, if you have a property called ID in the MyClass, the GridView displaying the records, should have the name of the BoundField representing the ID as "ID", you see how names match?
  • No more needed to list all Select,Update,Insert,Delete parameters in the ObjectDataSource. At runtime, an instance of type MyClass is created for us out of the Data-Bound Control (example: GridView) and sent to the data mapper's methods!

I asked myself, wouldn't that be waste of time if I am sending the whole object to the Delete Method, in a time, I only need for example ID to delete a record? Well, the answer came back directly from the ObjectDataSource as follows: The proccess is so inteligent that when the Delete Button is clicked, the key specified in the DataKeyNames property of the GridView for example, is supplied to the MyClass instance, so only the ID is filled and the rest of fields are igonored. Isn't that great?

Check this simple example to see How Stuff Works ;)

GridView + ObjectDataSource       

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataSourceID="ObjectDataSource1">
            <Columns>
                <asp:BoundField DataField="LastName" HeaderText="LastName" SortExpression="LastName" />
                <asp:BoundField ReadOnly="true" DataField="EmployeeId" HeaderText="EmployeeId" SortExpression="EmployeeId" />
                <asp:BoundField DataField="FirstName" HeaderText="FirstName" SortExpression="FirstName" />
            </Columns>
        </asp:GridView>
        &nbsp;</div>
        <asp:ObjectDataSource ID="ObjectDataSource1" runat="server" DataObjectTypeName="Employee"
            DeleteMethod="Delete" SelectMethod="Get" TypeName="EmployeeDal"></asp:ObjectDataSource>

Employee and EmployeeDal

public class Employee
{
    #region Private Members
    private int m_EmployeeId;
    private string m_FirstName;
    private string m_LastName;
    #endregion

    #region Constructors
    public Employee()
    { }

    public Employee(int p_EmployeeId, string p_FirstName, string p_LastName)
    {
        this.m_EmployeeId = p_EmployeeId;
        this.m_FirstName = p_FirstName;
        this.m_LastName = p_LastName;
    }
    #endregion

    #region Public Properties
    public int EmployeeId
    {
        get { return this.m_EmployeeId; }
        set { this.m_EmployeeId = value; }
    }

    public string FirstName
    {
        get { return this.m_FirstName; }
        set { this.m_FirstName = value; }
    }
    public string LastName
    {
        get { return this.m_LastName; }
        set { this.m_LastName = value; }
    }
    #endregion
}

--------------------

using System;
using System.Data;
using System.ComponentModel;
using System.Configuration;
using System.Collections.Generic;

[DataObjectAttribute]
public class EmployeeDal
{
    public EmployeeDal()
    {   }

    [DataObjectMethodAttribute(DataObjectMethodType.Delete, true)]
    public static void Delete(Employee p_Employee)
    {
        // your logic to delete a record using the parameter EmployeeId as follows
        int EmployeeId = p_Employee.EmployeeId;
    }
   
    [DataObjectMethodAttribute(DataObjectMethodType.Select, true)]
    public List<Employee> Get()
    {
        // your logic to retrieve all records

        return new List<Employee>();
    }
}

Hope this helps,

Regards

Tags:

Apr 17 2006

ASP.NET 2.0 Localize Control

Category: ASP.NET 2.0 - GeneralBil@l @ 08:26

In my research on Localization in ASP.NET 2.0, which is my topic of the next Community Night Session at Microsoft Office in Beirut, I passed by the <asp:Localize> control in ASP.NET 2.0.

This control inherits from the Literal Control. It is mainly used to display static text on a web page that is to be localized.

You might say, a Literal or Label can do the job for me, that is true. BUT, both a Label and Literal control, don't have design view editing. So, using the Localize, you can write down the text on the spot through the design view of the page.

You can also, put some text into the Localize control programmatically same as you do with the Label and Literal Control.

However, styling of text is not allowed in a Localize control, as in the Label control. However, you can always hug the Localize control with a CSS class for formatting issues ;)

Hope this helps you,

Regards

Tags:

Apr 16 2006

DotNetNuke Module - FixLogin

Category: DotNetNukeBil@l @ 13:53

In a new DotNetNuke 3.2.2 website I am working on, supposedly will be online this coming week, I faced the following problem:

DotNetNuke uses by default a Login Page. So, when users come to sign in, if authenticated they will be redirect to the page they were accessing it.

The problem with the default Login page is that, all modules added to the different areas of the site, we will not be shown when the login page is displaying.

To overcome this problem, I created a new page, with all the needed modules placed in their locations, and placed an Account Login module. Then through the Site Settings, I made this page the *Login Page* of the website.

Now users, when they come to login, they will be using my custom login page, showing all modules in their proper locations, as if the login page now, acts like any other page in the website, with the exception, it is being used to login users.

Another problem arises here!!

What happens now is that, when users sign in, they are redirected to the custom login page, which is something that confuses users, since they have just signed in, and now they are faced with the login page again.

My analysis for this problem is that, the Account Login module is functioning normally, it has redirected users to the previous page coming from, and this is ok. However, it seems that the DNN default Login page and the Account Login Module act as single component, so the page and the module is one single component, and hence the Account Login module will not consider the DNN default login page as a previous page coming from, and it will function as required. 


So, having this problem of the custom login page, forced me to look for some help online, however, could not find it. I had to solve it on my own. 

How?


I created a simple module, called FixLogin. This module is free to download and use and can be found at:
https://bhaidar.net/cs/files/5/april/entry270.aspx 

What this module does, is check if the Current Request is authenticated, if true, and then redirects the user to a page. This page can be set by using the module settings itself.

Once you add a new module definition, you will need to add two controls:

  • FixLogin.ascx
  • FixLoginSettings.ascx

The first is the default control, which should not have any key associated with it and is of type View. The second control is the settings control. 

Now, you can place this module on the custom login page you have in your website. Make sure to configure the settings of this module before using it. If you didn’t configure the module, no redirect will happen.

From the Action’s menu of the module, go to Settings, and specify the page to redirect to if the request is authenticated.