RangeValidator in WebForms Page Fails with error - webforms

I have been tasked with maintaining an older webforms application without much training or experience.
I was asked to add a new field to an existing table and expose it in the web page. Here's the code to do that, which I modeled on other existing fields and code.
<asp:TextBox ID="PortableBarrelCompressionValuetextBox"
runat="server"
SkinID="FVTextBox"
Text='<%# Bind("PortableBarrelCompressionValue") %>'
<asp:RangeValidator
ID="RangeValidatorPortableBarrelCompressionValuetextBox"
runat="server"
ControlToValidate="PortableBarrelCompressionValuetextBox"
CssClass="failureNotification"
Display="Dynamic"
ErrorMessage="Whole Numbers Between 0 and 9999"
MaximumValue="9999"
MinimumValue="0"
Type="Integer"
Text='<%# Eval("PortableBarrelCompressionValue") %>'>
</asp:RangeValidator>
This only works correctly when the existing value is non-null (and of course, within range). If I change a valid number, say 22, to a different valid number, 200, it saves the change as expected.
However, if the value on an existing record was null and I try to add an integer, it fails with the error message:
Value {" is not a valid value for Int32."} System.Exception
It also fails if there is an existing, valid, value which deleted, with the same error.
This field is not required, so I have to allow for Nulls here.
I've learned enough in the last two days to decide this is happening because the field is an integer and that the Null can't be converted to a string for the validation (at least that's what I'm assuming now).
If that is true, and this is the problem, I need to find a way to resolve that.
Am I on the right track?
Is there a way to provide a validation that will also accept nulls in this field, in addition to integers in the proper range?
Thanks in advance.

This does not throw your error
<%# Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="FredWebForm.WebForm1" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="FeaturedContent" runat="server">
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
<%--bind only used with controls that have datasource eg grid--%>
<asp:TextBox runat="server" Text='<%# GetStatus("PortableBarrelCompressionValue") %>' ID="MyTextBox" />
<asp:RangeValidator
ID="RangeValidatorPortableBarrelCompressionValuetextBox"
runat="server"
ControlToValidate="MyTextBox"
CssClass="failureNotification"
Display="Dynamic"
ErrorMessage="Whole Numbers Between 0 and 9999"
MaximumValue="9999"
MinimumValue="0"
Type="Integer"
Text='Needs to be a number between 0 and 9999'>
</asp:RangeValidator>
</asp:Content>
Code behind
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
DataBind();
}
}
protected string GetStatus(string theID)
{
return null;
}
}

I finally figured out my error.
It was not in this section at all.
I didn't realize that the definition of the LingDataSource for the form has to be updated as well.
Once I added this line:
<asp:Parameter Name="PortableBarrelCompressionValue"
ConvertEmptyStringToNull="true" />
It came back to life.
Thanks for all the support.

Related

Changing the message when using UpdateProgress

I dont know if this is possible or not but I was wondering if there is a way to change a message in the UpdateProgress when using Ajax. I tried put the message in a label and for some reason i cant do it that way so just wondering you can how to do that. Here is what I have below.
<asp:UpdateProgress ID="UpdateProgress1" runat="server">
<ProgressTemplate>
Logining In...
</ProgressTemplate>
</asp:UpdateProgress>
Just do like this
Page:
<asp:UpdateProgress ID="UpdateProgress1" runat="server" ClientIDMode="Static">
<ProgressTemplate>
<div id="overlay">
<asp:Label ID="lbl_wait" runat="server" clientIDMode="Static">Logining In...</asp:Label>
</div>
</ProgressTemplate>
</asp:UpdateProgress>
Code:
(UpdateProgress1.FindControl("lbl_wait") as System.Web.UI.WebControls.Label).Text = "Logged In...";

Only one instance of a ScriptManager can be added

Why do I get this error message: Only one instance of a ScriptManager can be added to the page?
I haven't been using HTML comment to hide an ASP.NET server tag and there is no other ScriptManager in the entire project.
Markup:
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
</div>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Label ID="lblCount" CssClass="LikeCount" Text='<%#Eval("LikeCount") %>' runat="server"></asp:Label>
<asp:LinkButton ID="lbAddOne" CssClass="LikeAddOne" Text="+1" runat="server" OnClick="lbAddOne_Click" CommandArgument='<%#Eval("ReviewID") %>'></asp:LinkButton>
</ContentTemplate>
</asp:UpdatePanel>
Code-behind:
protected void lbAddOne_Click(object sender, EventArgs e)
{
LinkButton _sender = (LinkButton)sender;
string ReviewID = _sender.CommandArgument;
int UserID = ((User)Session["LoggedInUser"]).UserID;
lblCount.Text = (int.Parse(lblCount.Text) + 1).ToString();
CategoryAccess.AddLikeReview(ReviewID, UserID);
}
just add a reference to scriptmanager in the masterpage, then it will be available to any page referencing the master. this will be easier to maintain in the long run rather than adding references to individual pages.

Loop through XML elements in XmlDataSource in code behind

I have an XmlDataSource and a GridView on my page. On the Page_Load event, I apply an XPath to filter the xml elements according to the input of the user, LexiqueXmlDataSource.XPath = 'Some_XPath_here'; and it works just ok.
What I want is to access the elements that the XmlDataSource returns from codebehind after applying the XPath expression (and hence get their number).
I tried the GetXmlDocument() method but it returns the whole original Xml file rather than the filtered elements with XPath.
EDIT:
here is some code and the scenario I want:
protected void Page_Load(object sender, EventArgs e)
{
string xpath = "/lexique/item[starts-with(#acronym, '" + filter + "')]";
LexiqueXmlDataSource.XPath = xpath;
// Here the XmlDataSource have filtered the xml elements to return to the GridView
//I want to know how many element passed this filter using the XmlDataSource itself
}
Thank you.
Here is what I could come up with.
For the number of hits. Use the GridView row count. Indeed the GetXmlDocument.ChildNodes.Count always return the number of lexical items, not the number of hits whan the XPath expression is applied.
Test XML
<?xml version="1.0" encoding="utf-8" ?>
<lexique>
<item acronym="WPF" value="Windows Presentation Foundation"/>
<item acronym="SO" value="StackOverflow"/>
</lexique>
Minimalist ASP.net Page
<%# Page Language="vb" AutoEventWireup="false" CodeBehind="xmlgrid.aspx.vb" Inherits="WebApplication1.WebForm1" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="FilterLabel" runat="server" Text="Acronym starting with:"></asp:Label>
<asp:TextBox ID="FilterTextBox" runat="server"></asp:TextBox>
<asp:XmlDataSource ID="LexiqueXmlDataSource" runat="server" DataFile="~/lexique.xml">
</asp:XmlDataSource>
<asp:GridView ID="LexiqueGrid" runat="server" AllowSorting="true" BorderStyle="Groove">
<Columns>
<asp:TemplateField HeaderText="Acronym">
<ItemTemplate>
<%# XPath("/lexique/item/#acronym")%>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Value">
<ItemTemplate>
<%# XPath("/lexique/item/#value")%>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
<asp:Label ID="Hits" runat="server" Text="Acronyms found"></asp:Label>
<asp:Button ID="Submit" runat="server" Text="Search" />
</div>
</form>
</body>
</html>
Code Behind
Public Class WebForm1
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim XPath As String
If String.IsNullOrEmpty(FilterTextBox.Text) Then
XPath = "/lexique/item"
Else
XPath = "/lexique/item[starts-with(#acronym, '" + FilterTextBox.Text + "')]"
End If
LexiqueXmlDataSource.XPath = XPath
LexiqueXmlDataSource.DataBind()
LexiqueGrid.DataSource = LexiqueXmlDataSource
LexiqueGrid.DataBind()
Hits.Text = "Selected " & LexiqueGrid.Rows.Count & " out of " &
LexiqueXmlDataSource.GetXmlDocument.ChildNodes.Count & "Acronyms loaded."
End Sub
End Class
If I understand correctly you want to know the number of returned elements. Would the XPath expression 'count(Some_XPath_here)' not give this number of hits ?
here is some code and the scenario I
want:
protected void Page_Load(object sender, EventArgs e)
{
string xpath = "/lexique/item[starts-with(#acronym, '" + filter + "')]";
LexiqueXmlDataSource.XPath = xpath;
// Here the XmlDataSource have filtered the xml elements to return to the GridView
//I want to know how many element passed this filter using the XmlDataSource itself
}
Just use and evaluate this XPath expression:
string xpath2 = "count(/lexique/item[starts-with(#acronym, '" + filter + "')])";

jQuery client side validation not working with MVC 3 MvcContrib.FluentHtml

Using MVC 3 RTM and MvcContrib/FluentHtml version 3.0.51.0, I can't get the jQuery client side validation to work. Server side validation works fine, and returns showing the correct validation summary, etc. But the form post always tries to hit the server-side post controller action when it should have stopped on the client side to display the validation error.
Any ideas of what I'm missing? Could the latest version of MvcContrib/FluentHtml be incompatible with jQuery client validation?
Here's my code:
Web.config has:
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
Site.Master page has:
<script src="<%= Url.Content("~/Assets/JavaScript/jquery-1.4.4.min.js")%>" type="text/javascript"></script>
<script src="<%= Url.Content("~/Assets/JavaScript/jquery-ui-1.8.7.min.js")%>" type="text/javascript"></script>
<script src="<%= Url.Content("~/Assets/JavaScript/jquery.validate.min.js")%>" type="text/javascript"></script>
<script src="<%= Url.Content("~/Assets/JavaScript/jquery.validate.unobtrusive.min.js")%>" type="text/javascript"></script>
View page inherits from MvcContrib's ModelViewPage:
Here's the view page:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="ModelViewPage<MaintainReferralAgencyDetailVM>" %>
<%# Import Namespace="OASIS3G.Controllers" %>
<%# Import Namespace="OASIS3G.ViewModels" %>
<%# Import Namespace="JCDCHelper.Extension"%>
<%# Import Namespace="MvcContrib.FluentHtml" %>
<%# Import Namespace="System.Web.Mvc" %>
<%# Import Namespace="System.Web.Mvc.Html" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<% using (Html.BeginForm()) %>
<% { %>
<h1>Referral Agency Detail</h1>
<%= Html.ValidationSummary(false) %>
<table class="NoBorder">
<tr>
<td class="NoBorder SubmitFormLeftColumn"><span class="required">* </span>Zip Code:</td>
<td class="NoBorder"><%= this.TextBox(x => x.ReferralAgency.ContactInformation.Zipcode) %> Example: 99999 or 999990000
<%= Html.ValidationMessageFor(x=>x.ReferralAgency.ContactInformation.Zipcode) %>
</td>
</tr>
</table>
<input type="submit" value="Submit" />
<% } %>
</asp:Content>
Here's the controller post action:
[HttpPost]
public ActionResult MaintainReferralAgencyDetail(MaintainReferralAgencyDetailVM userInputs)
{
// I shouldn't reach this when I submit the form with a blank Zipcode, but I do:
if (ModelState.IsValid)
{
Here's the entity object with the Required field:
[Serializable]
public class ContactInformationEO
{
public virtual Int64 AddressId { get; set; }
[Required]
public virtual string Zipcode { get; set; }
I figured it out, it's definitely MvcContrib messing it up. I originally thought MvcContrib wasn't a factor because when I had changed from MvcContrib's ModelViewPage to Mvc.ViewPage, I switched the "this.TextBox" to "Html.TextBox", it still didn't work. However, I just discovered that I need to switch the control to "Html.EditorFor" instead of "Html.TextBox".
I've googled for a few minutes and it doesnt look like MvcContrib version 3.0.51.0 supports jquery client-side validation with any equivalent of EditorFor, so I'll have to just rip it out and use the native MVC controls.
You can see an article with a complete solution of my approach here: automatically-validate-and-format-data-with-asp-net-mvc-and-jquery
Just ran headlong into this problem, looks like Scott Kirkland has a solution.

Button command firing twice with ButtonField inside GridView inside UpdatePanel with FireFox

I have an update panel which contains a GridView, inside which is a ButtonField. Whenever I press the button I see Firefox doing two POST's (via Firebug). One gets aborted right away, but does reach the server. This causes problems on my server side code as the command (a copy) gets executed twice.
IE6 and IE8 do not exhibit this behavior.
Anyone know what's causing this or what I can do about it?
I've managed to reproduce the problem to its bare minimum on this page:
<form id="form1" runat="server">
<asp:XmlDataSource ID="XmlDataSource1" runat="server">
<Data>
<bla>
<wibble wobble="1" />
</bla></Data>
</asp:XmlDataSource>
<asp:ScriptManager runat="server"></asp:ScriptManager>
<asp:UpdatePanel runat="server">
<ContentTemplate>
<asp:Label runat="server" ID="Counter" Text="0"></asp:Label>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
DataSourceID="XmlDataSource1" onrowcommand="GridView1_RowCommand">
<Columns>
<asp:BoundField DataField="wobble" HeaderText="wobble"
SortExpression="wobble" />
<asp:ButtonField HeaderText="wobble" CommandName="IncrementWobble"
SortExpression="wobble" ButtonType="Image" ImageUrl="icons/page_copy.png" Text="increment" />
</Columns>
</asp:GridView>
</ContentTemplate>
</asp:UpdatePanel>
</form>
While making this small version, I noticed that the problem only occurs with ButtonType="Image" and not with ButtonType="Button".
For completeness, the event handler:
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "IncrementWobble")
{
int count = Int32.Parse(Counter.Text) + 1;
Counter.Text = count.ToString();
}
}
From here, I found a workaround:
Replacing the ButtonField with a TemplateField containing an ImageButton works around the problem. Good enough for me, but still seems like a bug in either ASP .NET or FireFox.

Resources