Tech Tidbits - Ruby, Ruby On Rails, Merb, .Net, Javascript, jQuery, Ajax, CSS...and other random bits and pieces.

Saturday, November 17, 2007

Identify Button Clicked in GridView

I had a GridView with a ButtonField used to Select a record to display a User's details in a DetailsView. I wanted a second button to display different form for changing a Users's password, since I wanted that to be a separate option.

GridView (usersGrid):

<asp:ButtonField CommandName="Select" Text="Select" />
<asp:TemplateField>
<ItemTemplate>
<asp:LinkButton runat="server" ID="changePasswordButton" Text="Change Password" OnClick="usersGrid_SelectRow" />
</ItemTemplate>
</asp:TemplateFild>


Code Behind:

protected void usersGrid_SelectRow(object sender, EventArgs e)
{
GridViewRow row = (GridViewRow)((LinkButton)sender).Parent.Parent;
usersGrid.SelectedIndex = row.RowIndex;

MyDatabase.DBUtil = new MyDatabase.DBUtil();
changePasswordDetails.DataSource = DB.GetUser(Int16.Parse(usersGrid.SelectedValue.ToString());
changePasswordDetails.ChangeMode(DetailsViewMode.ReadOnly);
userDeatils.Visible = false;
changePasswordDetails.Visible = true;
changePasswordDetails.DataKeyNames = new string[] { "UserID" };
changePasswordDetails.DataBind();
}

Friday, November 9, 2007

.NET Smart Delete (Details View Client-side delete confirmation)

I was working on a database-driven web site and I needed a way to make sure that the admin couldn't delete all the admin user accounts (that was simple enough), but I also wanted a javascript confirmation popup when an admin did delete accounts.

I found exactly what I was looking for on Dino Esposito's WebLog on his post ASP.NET Today: Smart Delete:


DetailsView and FormView controls support delete operations and delegate the execution to the underlying data source control. If the data source control is configured to execute the delete operation, all works fine, otherwise an exception is thrown.

The DetailsView generates command buttons automatically and doesn't expose them directly to page code. How can you add a bit of Javascript code to ask for confirmation? Here's the code.


protected void DetailsView1_ItemCreated(object sender, EventArgs e)
{
// Test FooterRow to make sure all rows have been created
if (DetailsView1.FooterRow != null)
{
// The command bar is the last element in the Rows collection
int commandRowIndex = DetailsView1.Rows.Count-1;
DetailsViewRow commandRow = DetailsView1.Rows[commandRowIndex];

// Look for the DELETE button
DataControlFieldCell cell = (DataControlFieldCell) commandRow.Controls[0];
foreach(Control ctl in cell.Controls)
{
LinkButton link = ctl as LinkButton;
if (link != null)
{
if (link.CommandName == "Delete")
{
link.ToolTip = "Click here to delete";
link.OnClientClick = "return confirm('Do you really want to delete this record?');";
}
}
}
}


The ItemCreated event doesn't provide any information about the row being created. However, it can be figured out that the footer row is always created and is always the last row to be created. If the FooterRow object is not null, you can conclude that all rows have been created, including the command bar. The command bar is the first row after the data rows and is stored in the Rows collection--it's the last element in the collection. The command bar is a table row (type is DetailsViewRow) and contains a cell (type is DataControlFieldCell). The cell contains as many link buttons (type is DataControlLinkButton) as there are commands. Delete, Edit, New, Update, Cancel are the command names used and useful to identify the right button.

The FormView is fully templated and lets you manually define appearance and behavior of command buttons. If you place a custom button, or want to use a custom command name for a standard button (Edit, New, Delete), here's how to detect the click on the button. You start by adding a handler for ItemCommand. The code below shows how to deal with a custom Delete button that checks if the bound data source control is enabled for deletion before proceeding.


protected void FormView1_ItemCommand(object sender, FormViewCommandEventArgs e)
{
if (e.CommandName == "SmartDelete")
{
IDataSource obj = (IDataSource) FindControl(FormView1.DataSourceID);
DataSourceView view = obj.GetView("DefaultView");
if (!view.CanDelete) {
Response.Write("Sorry, you can't delete");
return;
}
else
FormView1.DeleteItem();
}
}

Tuesday, November 6, 2007

Formatting Date Field in Grid View

Due to a bug fix in .NET 2.0, HtmlEncode must be set to False for date formatting to give expected results:


<asp:BoundField DataField="AgendaDate" HeaderText="Agenda Date" SortExpression="AgendaDate" DataFormatString="{0:yyyy-MM-dd}" HtmlEncode=False />


In a Details View using TemplateFields:


<ItemTemplate>
  <asp:Label ID="agendaDateLabel" runat="server" Text='<%# Eval("AgendaDate", "{0:yyyy-MM-dd}") %>'></asp:Label>
</ItemTemplate>

Saturday, November 3, 2007

SQL Server 2005 Check Constraint

I wanted to use something like the MySQL Enum constraint in SQL Server to limit the values allowed in a column...

I ended up using a separate table and a foreign key for this, but never the less, here's how to use the Check constraint, in my case, to limit RecordStatus to contain only 'Active' or 'Inactive':


CREATE TABLE NewsItems (
NewsItemID int IDENTITY NOT NULL PRIMARY KEY,
RecordStatus nvarchar(10) NOT NULL DEFAULT 'ACTIVE' CHECK (RecordStatus IN ('Active', 'Inactive'))
);

Friday, October 19, 2007

ASP .NET - C# Decimal Comparison

A little more shopping cart hacking. Here's how do to Decimal comparisons in C#:


public static decimal GetShippingCost()
{
decimal sum;
decimal shippingCost;
sum = GetSubtotal() - GetCouponDiscount();
if (sum < 0)
sum = 0;

if ( Decimal.Compare(sum, 26.95m) <= 0 )
shippingCost = 8.95m;
else if ( Decimal.Compare(sum, 35.95m) <= 0 )
shippingCost = 11.95m;
else if ( Decimal.Compare(sum, 45.95m) <= 0 )
shippingCost = 12.95m;
else if ( Decimal .Compare(sum, 55.95m) <= 0 )
shippingCost = 16.95m;
else if ( Decimal.Compare(sum, 74.95m) <= 0 )
shippingCost = 18.95m;
else if ( Decimal.Compare(sum, 99.95m) <= 0 )
shippingCost = 20.95m;
else if ( Decimal.Compare(sum, 119.95m) <= 0 )
shippingCost = 22.95m;
else if (Decimal.Compare(sum, 139.95m) <= 0 )
shippingCost = 24.95m;
else if (Decimal.Compare (sum, 159.95m) <= 0 )
shippingCost = 26.95m;
else if (Decimal.Compare(sum, 199.95m) <= 0 )
shippingCost = 29.95m;
else if ( Decimal.Compare(sum, 249.95m ) <= 0 )
shippingCost = 32.95m;
else if (Decimal.Compare(sum, 299.95m) <= 0 )
shippingCost = 34.95m;
else
shippingCost = 34.95m;

return shippingCost;
}

ASP .NET - Redirecting to HTTPS

On a project where I had to install a third party shopping cart, one issue that came up was to make sure all the pages ran under https (many hard coded links used "http").

I put the following code in the Global.asax file:


protected void Application_BeginRequest(Object sender, EventArgs e)
{
if (Request.Url.Port != 443)
{
Response.Redirect ("https://www.yourdomain.com" + Request.Url.AbsolutePath, true);
}
}


This uses


Request.IsSecureConnection


to determine if the call was made over SSL.

So


if (Request.IsSecureConnection)
{
Response.Write("HTTPS");
}
else
{
Response.Write("HTTP");
}



Another way to write this:


if (!Request.IsSecureConnection)
{
string serverName =HttpUtility.UrlEncode(Request.ServerVariables["SERVER_NAME"]);
string filePath = Request.FilePath;
Response.Redirect("https://" + serverName + filePath);
}

Thursday, October 18, 2007

Classic ASP: Sending e-mail (CDONTS -> CDOSYS)

One of today's jobs was fixing a mail script running on classic ASP that died after being moved to a new server. Attempting to send an email resulted in this error:


Microsoft VBScript runtime error '800a01ad'

ActiveX component can't create object: 'CDONTS.Newmail'

/aspmailer.asp, line 45


CDONTS has been deprecated and replaced with CDOSYS.

I updated aspmailer.asp (a somewhat redundantly named script) to use CDOSYS. After the update, I got this error:


The "SendUsing" configuration value is invalid.


So I still need a bit more code.

This site provided the needed fix:

http://classicasp.aspfaq.com/email/how-do-i-send-e-mail-with-cdo.html


<!--
METADATA
TYPE="typelib"
UUID="CD000000-8B95-11D1-82DB-00C04FB1625D"
NAME="CDO for Windows 2000 Library"
-->
<%
Set cdoConfig = CreateObject("CDO.Configuration")

With cdoConfig.Fields
.Item(cdoSendUsingMethod) = cdoSendUsingPort
.Item(cdoSMTPServer) = "<enter_mail.server_here>"
.Update
End With

Set cdoMessage = CreateObject("CDO.Message")

With cdoMessage
Set .Configuration = cdoConfig
.From = "from@me.com"
.To = "to@me.com"
.Subject = "Sample CDO Message"
.TextBody = "This is a test for CDO.message"
.Send
End With

Set cdoMessage = Nothing
Set cdoConfig = Nothing
%>


Replace <enter_mail.server_here> with the name or IP of your SMTP mail server ("localhost" may do the trick).

The other example provided is as follows:


<%
sch = "http://schemas.microsoft.com/cdo/configuration/"

Set cdoConfig = CreateObject("CDO.Configuration")

With cdoConfig.Fields
.Item(sch & "sendusing") = 2 ' cdoSendUsingPort
.Item(sch & "smtpserver") = "<enter_mail.server_here>"
.update
End With

Set cdoMessage = CreateObject("CDO.Message")

With cdoMessage
Set .Configuration = cdoConfig
.From = "from@me.com"
.To = "to@me.com"
.Subject = "Sample CDO Message"
.TextBody = "This is a test for CDO.message"
.Send
End With

Set cdoMessage = Nothing
Set cdoConfig = Nothing
%>

About Me

My photo
Developer (Ruby on Rails, iOS), musician/composer, Buddhist, HSP, Vegan, Aspie.

Labels