Custom bussiness objects for ASP.NET 2.0 object datasources

In ASP.NET 2.0 the gridview control is quite nice. By just setting some
properties you can create a web application whose grid data can be edited by the
end-user without the need to write all the plumbing code by hand. Which is quite
a big step forward from 1.x. For this to work the gridview communciates with the
data through a datasource. Most of these datasources, like the sqlDatasource,
communicate directly with the database. Having them on your webform leads to
monolithic webapps.

The way to layer an app is using an objectdatasource. In this article
on the SDN site (you have to register to read
the article. registration is free) I explored a way to use an ASP.NET dataset
2.0 style as bussinessobject. The story manages to separate the database access
from the web-forms into two separate dll’s. Two layers, to turn these into tiers
you need a RPC protocol for them to communicate over machine boundaries. For the
SDN user group I’ll be doing a presentation on
objectdatasources april 1st (no joke) to continue with this part of the story.
Here some first shots at the subject.

The properties of the 2.0 dataset suggest a role for webservices; all those
diagrams in team system suggest that as well. But browsing and googling around
leave the subject quite misty. The “generate webmethods” option in the dataset
will not make it into the final version. I havn’t seen beta2 yet, for the time
being it will take some custom work. As a demo a webservice to wrap up
functionality of the dataset. This webservice will expose some of the methods
needed by the datasource. (The dataset used is described in the article.)

[WebServiceBinding(ConformanceClaims=WsiClaims.BP10,EmitConformanceClaims =
true)]

public class
Service : System.Web.Services.WebService {

    [WebMethod]
    public DataSetInvoices InvoiceList()
   
{
        DataSetInvoices ds = new DataSetInvoices();
       
InvoicesTableAdapter ta = new InvoicesTableAdapter();
       
ta.FillList(ds);
        return ds;
    }

    [WebMethod]
    public void UpdateInvoice(System.DateTime InvoiceDate,
int InvoiceNumber, int idCustomer, string Description, int
Original_idInvoice)
    {
        InvoicesTableAdapter ta = new
InvoicesTableAdapter();
        ta.Update(InvoiceDate, InvoiceNumber,
idCustomer, Description, Original_idInvoice);
    }

}

The objectdatasource does not really work with a full dataset but with it’s
tableadapaters. A dataset is fully SOAP-serializable, a tableadapater is not.
You can try to make the webservice return a tableadapter, the result will be
that all the VS2005 auto-magic will wrap the adapter up in a dataset
nevertheless.

The original plan might have been to have the objectdatasource directly
consume the webservice. For now we need a simple wrapper class which interacts
with the webservice and exposes the functionality in the format the
objectdatasource wants. The object datasource property builder lists classes
available to provide the bussiness object.

It will look for classes decorated
with the System.ComponentModel.DataObject attribute.
The datasource looks for methods on the dataobject to retreive, update, insert
or delete data. The property builder will look for methods decorated with the
System.ComponentModel.DataObjectMethod attribute. The
constructor of this attribute takes a member of the
System.ComponentModel.DataObjectMethodType enumeration
as parameter. There is a Select, Fill, Update, Insert and Delete member.

The objectdatasource looks for a matching method on the bussiness-object.
Runtime it will look for a method whose parameter names match the parameters to
be sent to the method. The names of the parameter have to match exactly, the
casing of these names does not have to match. When Reflection finds no match an
exception is thrown. The error message tell you what parameter names are
expected. 

The type of the parameters is not checked. When invoking the method the
objectdatasource will try to convert the parameters to the desired type, when
this is not possible an execption is thrown. The callstack of the exception
clearly shows the attempt Reflection has made.

In the gridview on the invoices the date, number, customer id and description
columns can be edited. An object of this class can serve as a datasource:

[System.ComponentModel.DataObject]
public class BOwrapper
{

   
[System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Select)]
   
public DataHost.DataSetInvoices.InvoicesDataTable InvoicesByName()
   
{
        DataHost.Service ws = new DataHost.Service();
       
DataHost.DataSetInvoices ds = ws.InvoiceList();
        return
ds.Invoices;
    }

   
[System.ComponentModel.DataObjectMethod(System.ComponentModel.DataObjectMethodType.Update)]
   
public virtual int UpdateInvoice(DateTime InvoiceDate, int InvoiceNumber, int
idCustomer, string Description, int Original_idInvoice)
    {
       
DataHost.Service ws = new DataHost.Service();
       
ws.UpdateInvoice(InvoiceDate, InvoiceNumber, idCustomer, Description,
Original_idInvoice);
        return 1;
    }

}

The BOwrapper class exposes methods which the objectdatasource (and the
gridview using that) understands. In the implementation of the mehods it does
invoke the webservice. In this example it is a straightforward synchronous
invocation. It’s up to you to attach any bell or horn you wish. Or implement
another RPC protocol, instead of getting to the bussiness object via a
webservice you might want to use remoting.

The result is that I have these layers

  • Webbrowser
  • Webform with objectdatasource
  • BOwrapper (can have its own dll)
  • Webservice
  • Database

There are several ways to slice these layers into several physical tiers. And
I still have fully updatable data in the browser without having to code my own
plumbing. That’s something I really want to leave behind in 1.1.

 

This entry was posted in ASP.NET, Data. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://codebetter.com/blogs/peter.van.ooijen/ pvanooijen

    Right !
    I’m sorry, don’t speak Russian (?)

  • lbr

    f disyatke i niipet !