Archive for June, 2011

GridView Insert with ObjectDataSource: Lessons Learnt

June 14, 2011

Was playing around today with implementing a full CRUD interface to a Database table using GridView and ObjectDataSource. I had a bit of trouble getting Insert functionality to work and here’s what I learnt:

DataObjectTypeName SHOULD BE OMITTED if you are using Insert operations via your ODS.

Setting the ODS property DataObjectTypeName is meant to allow you to pass a Business or Domain object as a single parameter, rather than a list of parameters, one per member, to your ODS Inserts and Updates. While this seems to work fine for Updates, the ODS Insert will fail since its internal Dictionary of Object members is not initialised. This appears to be a bug in the ODS.

There are a couple of workarounds for this: you can create the Dictionary yourself from the ODS DataSource, or you can create a your custom Business object from the InsertParameter list. But if you don’t feel in the mood for workarounds you are stuck with omitting the DataObjectTypeName property and specifying the list of parameters to your Insert in the markup for the ODS

InsertParameters
asp:Parameter Name="CountryCode" /
asp:Parameter Name="CountryName" /
asp:Parameter Name="ISDCode" /
/InsertParameters

ODS Delete Parameter Will Be Inferred From DataKeys Member Of The GridView

Given a GridView of the following definition:
asp:GridView ID="gvTrial" runat="server" DataKeyNames="CountryCode"

NO DeleteParameter is required in the ODS markup and the DeleteMethod with the single parameter string CountryCode will be invoked from the TypeName (DataAccess) class specified in the ODS markup.

LinkButtons Defined in the GridView Control Template Will Trigger The ODS TypeName (DataAccess) Methods
You just need to give them the standard CommandNames that GridViews give to their Command Buttons. So given the following Button Definitions in the GridView Template:

asp:TemplateField
EditItemTemplate
asp:LinkButton ID="btnUpdate" runat="server" Text="Update" CommandName="Update" /
asp:LinkButton ID="btnCancel" runat="server" Text="Cancel" CommandName="Cancel" /
/EditItemTemplate
ItemTemplate
asp:LinkButton ID="btnEdit" runat="server" Text="Edit" CommandName="Edit" /
/ItemTemplate
FooterTemplate
asp:LinkButton ID="btnInsert" runat="server" Text="Insert" OnClick="lbInsert_OnClick" /
/FooterTemplate
/asp:TemplateField
asp:CommandField ShowDeleteButton="true" /

The Update and Delete methods on the TypeName (DataAccess) class will be fired automatically when the Update and Delete buttons are clicked.

Firing Insert From GridView Footer

This link shows the basic interface I used, with the Insert operation being fired from a LinkButton in the GridView Footer Row. As noted above, the Insert Parameters must be specified in the ODS Markup.

Insert From GridView Footer Where DataSource Is Empty
If your datasource is empty, the GridView will not render, so you wont get a Footer and you wont be able to Insert. So, add an empty record to the DataSource On the ODS SelectMethod, then hide the empty row during OnRowDataBound

The Final ODS

asp:ObjectDataSource runat="server" ID="odsCountry" TypeName="CountrySource" OnInserting="odsCountry_Inserting"
SelectMethod="GetCountries" UpdateMethod="UpdateCountry" InsertMethod="InsertCountry" DeleteMethod="DeleteCountry">
InsertParameters>
asp:Parameter Name="CountryCode" /
asp:Parameter Name="CountryName" /
asp:Parameter Name="ISDCode" /
/InsertParameters
/asp:ObjectDataSource

The GridView


asp:GridView ID="gvTrial" runat="server" DataKeyNames="CountryCode" EmptyDataText="No country data" DataSourceID="odsCountry"
AllowPaging="true" AllowSorting="true" AutoGenerateColumns="false" ShowFooter="true" OnRowDataBound="gvTrial_RowDataBound"

/EditItemTemplate
ItemTemplate
asp:LinkButton ID="btnEdit" runat="server" Text="Edit" CommandName="Edit" /
/ItemTemplate
FooterTemplate
asp:LinkButton ID="btnInsert" runat="server" Text="Insert" OnClick="lbInsert_OnClick" /
/FooterTemplate
/asp:TemplateField
asp:TemplateField
EditItemTemplate
asp:TextBox ID="tbCountryCode" runat="server" Text=''/asp:TextBox
/EditItemTemplate
ItemTemplate
asp:Label ID="lbCountryCode" runat="server" Text=''/asp:Label
/ItemTemplate
FooterTemplate
asp:TextBox ID="tbNewCountryCode" runat="server"></asp:TextBox
/FooterTemplate
/asp:TemplateField
asp:TemplateField
EditItemTemplate
asp:TextBox ID="tbCountryName" runat="server" Text=''/asp:TextBox
/EditItemTemplate
ItemTemplate
asp:Label ID="lbCountryName" runat="server" Text=''/asp:Label
/ItemTemplate
FooterTemplate
asp:TextBox ID="tbNewCountryName" runat="server"/asp:TextBox
/FooterTemplate
/asp:TemplateField
asp:TemplateField
EditItemTemplate
asp:TextBox ID="tbISDCode" runat="server" Text=''/asp:TextBox
/EditItemTemplate
ItemTemplate
asp:Label ID="lbISDCode" runat="server" Text=''>/asp:Label
/ItemTemplate
FooterTemplate
asp:TextBox ID="tbNewISDCode" runat="server"></asp:TextBox
/FooterTemplate
/asp:TemplateField
asp:CommandField ShowDeleteButton="true" /

/Columns
/asp:GridView

The TypeName (DataAccess) Class

Since DataObjectTypeName is omitted you MUST specify all parameters to the Insert and Update Methods. You cannot use your Business Class, which in my case would be ‘Country’. Use the MSDN example as your basic template:

public void UpdateCountry(string CountryCode, string CountryName, string ISDCode)
{
…whatever…
}

public void InsertCountry(string CountryCode, string CountryName, string ISDCode)
{
…whatever…
}

public void DeleteCountry(string CountryCode)
{
…whatever…
}

Winforms: Multiline Label; Display QueryString In Label Control

June 8, 2011

I was asked to produce a tiny Winforms app which would generate an encoded checksum for a QueryString that is consumed by one of our Web Applications. Because the encoding is based on an MD5 Hash of various data elements this Winforms app will enable our Testers and partner organisations to generate that checksum automagically.

When it came to displaying the generated checksum I encountered a problem or two:

  • When using a TEXTBOX, the QueryString would always break on the leading “?” leading to an ugly output, the first line being a “?” by itself
  • Labels are single line creatures meaning the QueryString was truncated i.e. only displayed up to the length of the Label control: there is no line wrapping
  • The ampersands in the query string were not output to the screen when using a Label control

Multiline Label
To achieve a Multiline Label: Set the Maximum Width property of the label to the same value as the Width property; Set the Height property of the label to a value that will enable it to show multiple lines; set the AutoSize property of the label to True. Thanks to Riff on the MSDN Visual Basic Forum.

Displaying Ampersand In Label Control
The reason that a Winforms Label control cannot display Anpersand is that “&” is interpereted as part the Mnemonic shortcut to the Text Field associated with the Label. To get around it, replace “&” wih “&&” in the string before displaying it or set useMnemonic to False. More details here c/o Cody Gray on Stack Overflow

Instigating the above fixes for my Label caused the Query String to display the full QueryString ampersands without breaking on the leading “?”. BUT, the value CANNOT be cut ‘n’ pasted from the Label control for use in a browser, which made it about as useful as a plywood firetruck at a refinery explosion.

So I went back to using a readonly TEXTBOX. However, semi-good news, the break-on-leading-question-mark-problem only occurs on strings shorter than the label width. So, I gave the users an option to prepend a base URL to the QueryString which covers the obscenity for long QueryStrings as the “?” is no longer the leading character.

Bypass Forms Authentication For One Page

June 6, 2011

Haven’t posted for a while and a reader said my blog was looking a bit stale, so here’s a short post to prove the waxen heart of the Tadpole is still beating.

I was asked to provide an alternative login page for a site. This page would be hosted in an IFrame which itself would live on a page in a wholly seperate domain. The users would enter their credentials in this alternative login page instead of the normal Login Page. Once the credentials were received and authenticated in the IFrame Page, the page would Redirect to a ‘Logged In’ page on our site.

It was trivial to perform the Authentication of the credentials but I soon saw the site was protected by Forms Authentication which meant that the Redirect would simply bring up our normal login page, thus requiring the users to Log In a redundant second time, a process was inclined to cause HeadDesking in unsuspecting users.
So to make the Alternative Login Page work I had to:

  • Exclude the Alternative Login Page from Forms Authentication (so the IFrame in which it was contained would display the Alternative Login Page and not the standard Login Page declared in the Forms Authentication section of web.config
  • Create a Forms Authentication Ticket for the user in the Alternative Login Page (so that the user would be recognised as authenticated once the redirection occurred and would not be referred back to the standard Login Page)

Excluding a page from Forms Authentication is quite simple: you configure anonymous access in web.config for that particular page by using the location section:

location path=”Register.aspx”
system.web
authorization
allow users=”*” /
/authorization
/system.web
/location

Here it is nicely laid out thanks to Geeks with Blogs. Congratulations! You are now an expert on UrlAuthorization

Here’s an excellent Overview Of Forms Authentication and its relationship with UrlAuthorization from the Tadpole’s horses mouth at Microsoft ASP.NET.