Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Procedure or function sProcName has too many arguments specified

Status
Not open for further replies.

mavalon

Programmer
Apr 18, 2003
125
0
0
US

I'm trying to learn SQL Server 2005 and ASP.NET 2.0. (I've been working with SQL 2000/.NET 1.1 until now.) I can't get past the following problem and hope one of you gurus can help:

The error I'm struggling with is: Procedure or function editArea has too many arguments specified.

NOte that this is a trimmed down version of the actual form page, which gets its ID from a GridView selection. That form also produces other errors, but I'm going to start with this error before tackling those.

The stored procedure follows:

Code:
ALTER PROCEDURE [dbo].[editArea]
[COLOR=green]
(
	-- Add the parameters for the stored procedure here
	@AreaId int,
	@Name varchar(50),
	@Description varchar(255) = NULL,
	@ParentId int = NULL,
	@TypeId tinyint,
	@Enabled bit,
	@original_Name varchar(50),
	@original_Description varchar(255) = NULL,
	@original_ParentId int = NULL,
	@original_TypeId tinyint,
	@original_Enabled bit,
	@Error bit OUTPUT,
	@Message varchar(255) OUTPUT
)[/color]
AS
BEGIN

	[COLOR=red]-- I do a bunch of stuff, mostly checking for valid 
        -- input and update if valid, set 
        -- message and error parameters[/color]

	[COLOR=green]RETURN [/color]
END

The Relevant section of the ASPX Page follows:

Code:
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
        <asp:FormView DefaultMode="Edit" ID="FormView1" runat="server" CellPadding="4" 
            DataKeyNames="AreaId" DataSourceID="SqlDataSource1" ForeColor="#333333">
            <FooterStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
            <RowStyle BackColor="#FFFBD6" ForeColor="#333333" />
            <EditItemTemplate>
                AreaId:
                <asp:Label ID="AreaIdLabel1" runat="server" Text='<%# Eval("AreaId") %>' />
                <br />
                Name:
                <asp:TextBox ID="NameTextBox" runat="server" Text='<%# Bind("Name") %>' />
                <br />
                Description:
                <asp:TextBox ID="DescriptionTextBox" runat="server" 
                    Text='<%# Bind("Description") %>' />
                <br />
                Rank:
                <asp:TextBox ID="RankTextBox" runat="server" Text='<%# Bind("Rank") %>' />
                <br />
                ParentId:
                <asp:TextBox ID="ParentIdTextBox" runat="server" 
                    Text='<%# Bind("ParentId") %>' />
                <br />
                TypeId:
                <asp:TextBox ID="TypeIdTextBox" runat="server" Text='<%# Bind("TypeId") %>' />
                <br />
                Enabled:
                <asp:CheckBox ID="EnabledCheckBox" runat="server" 
                    Checked='<%# Bind("Enabled") %>' />
                <br />
                <asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True" 
                    CommandName="Update" Text="Update" />
                &nbsp;<asp:LinkButton ID="UpdateCancelButton" runat="server" 
                    CausesValidation="False" CommandName="Cancel" Text="Cancel" />
            </EditItemTemplate>
            [COLOR=green]<!-- There are also item/insert templates here, but removed for this post -->[/color]
            <PagerStyle BackColor="#FFCC66" ForeColor="#333333" HorizontalAlign="Center" /> 
            <HeaderStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
        </asp:FormView>
        <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
            ConnectionString="<%$ ConnectionStrings:connString %>" 
            SelectCommand="SELECT AreaId, Name, Description, Rank, ParentId, TypeId, Enabled FROM Areas WHERE (AreaId = 2)" 
            UpdateCommand="editArea" UpdateCommandType="StoredProcedure">
[COLOR=green]
            <UpdateParameters>
                <asp:Parameter Name="AreaId" Type="Int32" />
                <asp:Parameter Name="Name" Type="String" />
                <asp:Parameter Name="Description" Type="String" />
                <asp:Parameter Name="ParentId" Type="Int32" />
                <asp:Parameter Name="TypeId" Type="Byte" />
                <asp:Parameter Name="Enabled" Type="Boolean" />
                <asp:Parameter Name="original_Name" Type="String" />
                <asp:Parameter Name="original_Description" Type="String" />
                <asp:Parameter Name="original_ParentId" Type="Int32" />
                <asp:Parameter Name="original_TypeId" Type="Byte" />
                <asp:Parameter Name="original_Enabled" Type="Boolean" />
                <asp:Parameter Direction="InputOutput" Name="Error" Type="Boolean" />
                <asp:Parameter Direction="InputOutput" Name="Message" Type="String" Size="255" />
            </UpdateParameters>
        </asp:SqlDataSource>[/color]
        [COLOR=red]<!-- if I remove the output parameters, I get the following error:
		"Procedure or function 'editArea' expects parameter '@Error', which was not supplied."

		Also, changing direction to "Output" has no effect -->[/color]

The relevant section of ASPX.VB:
Code:
    Protected Sub SqlDataSource1_Updated(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.SqlDataSourceStatusEventArgs) Handles SqlDataSource1.Updated
[COLOR=green]
    Dim msg As String = Convert.ToString(e.Command.Parameters("@Message").Value)[/color]
        label1.Text = msg
        label1.Visible = True
    End Sub
 
Using a SqlDataSource makes it very difficult to track down these types of errors due to the lack of step through debugging options with these controls.

However, if you mut use them, then start by using some SQL Server tools such as SQL Profiler and checking exactly what is being executed against the database. This should highlight which parameters are/aren't being passed.


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

Mark,
[URL unfurl="true"]http://aspnetlibrary.com[/url]
[URL unfurl="true"]http://mdssolutions.co.uk[/url] - Delivering professional ASP.NET solutions
[URL unfurl="true"]http://weblogs.asp.net/marksmith[/url]
 
Thank you for your quick response. I'm using SQL Server 2005 Express edition as well as Visual Web Developer 2008 Express Edition. Is SQL Profiler a part of either of those?

Also, I just tried to simplify the stored proc and removed output params. Now it's just a simple update (for testing purposes). After modifying the paramaters in the formview to match the procedure, i still get the same error. (All this time i thought it had something to do with the output parameters.)

I'm thinking that this FormView control will never really serve my purposes fully, as I will always need to use stored procedures (to return values after updates, deletes, inserts), bind dropdownlist controls, etc. In other words, it seems this control doesn't really simplify the process, but is only creating more of a headache for me. (Or maybe I just don't know how to use it.)

Do you recommend just creating my own forms and doing all the work in the code-behind like I always did in ASP.NET v1.1?
 
Is SQL Profiler a part of either of those?
I'm not sure. I would ask in the SQL Server forum or research on MSDN/Google.

Do you recommend just creating my own forms and doing all the work in the code-behind like I always did in ASP.NET v1.1?
Personally, I would yes. The data access side of things is very obscured using the method you have posted above and in the long run makes things harder to degug. As for the controls, the FormView shouldn't make things any more difficult for you but personally I don't use it very often and prefer the Repeater approach.


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

Mark,
[URL unfurl="true"]http://aspnetlibrary.com[/url]
[URL unfurl="true"]http://mdssolutions.co.uk[/url] - Delivering professional ASP.NET solutions
[URL unfurl="true"]http://weblogs.asp.net/marksmith[/url]
 
After only two days of pulling my hair out over this, I found the solution. And, man, is it ugly! Although, in the end, I’ll probably opt against using this control, I feel I should share my findings:

Firstly, since as far as I know SQL Server 2005 Express Edition doesn’t ship with SQL Profiler, I turned on trace:

Code-Behind:
Code:
[COLOR=blue]Protected Sub[/color] SqlDataSource1_Updating([COLOR=blue]ByVal[/color] sender [COLOR=blue]As Object[/color], [COLOR=blue]ByVal[/color] e [COLOR=blue]As[/color] System.Web.UI.WebControls.SqlDataSourceCommandEventArgs) [COLOR=blue]Handles[/color] SqlDataSource1.Deleting
 [COLOR=blue]For[/color] x [COLOR=blue]As Integer[/color] = 0 To e.Command.Parameters.Count - 1
            Trace.Write(e.Command.Parameters(x).ParameterName)
            Trace.Write(e.Command.Parameters(x).Value)
        [COLOR=blue]Next[/color]

    [COLOR=blue]End Sub[/color]
ASPX Page Directive:
Code:
<%@ Page [COLOR=red]Language[/color]=[COLOR=blue]"VB"[/color] [COLOR=red]AutoEventWireup[/color]=[COLOR=blue]"false"[/color] [COLOR=red]CodeFile[/color]=[COLOR=blue]"TestNoMaster.aspx.vb"[/color] [COLOR=red]Inherits[/color]=[COLOR=blue]"TestNoMaster"[/color] [COLOR=red] Trace[/color][COLOR=blue]="true"[/color] %>

A few things became clear:

[ol]
[li]All fields specified in the FormView’s select statement that were bound to controls using Bind(“FieldName”) were being passed as parameters to the Update stored procedure -- even the fields I didn’t need for the update. Since I didn’t have a “Rank” input parameter in my stored procedure, but bound it to a control, this meant there were, in fact, too many arguments being passed.[/li]

[li]The OldValuesParameterFormatString (In my case “original_”) was being passed as a parameter. (How dumb is that?!?) This accounted for a second extra argument being passed to the stored procedure. [/li]

[li]My ID field was not being passed to the stored procedure (Now that could be a problem.)[/li]

[li]My “original_” parameters (which would be used to check that data hasn’t changed since the user loaded the form) had no values. Thus my stored procedure, which checks the old values against the new, would assume that the record has been modified since loading the form, and therefore would not proceed to update the record.[/li]
[/ol]

Clearly, I had problems. The resolution to each follows:

The first problem, where all selected fields that are bound to controls are passed as parameters to the stored procedure, is resolved in any of the following ways:
[ul]
[li]If you need to select a field and display the value in a template as read only, pass it into the procedure as well (even though you won’t really be using it there!)[/li]

[li]Instead of using Bind(“FieldName”), use Eval(“FieldName”) when displaying in form template controls. – I haven’t tried this, but I’m assuming this would work.[/li]

[li]Remove the field from the select statement, and don’t bother to display it in a template.[/li]
[/ul]

The second issue: OldValuesParameterFormatString
[ul]
[li]I suppose this property is only useful if you’re letting the SqlDataSource do the updating for you. Since I had all the logic in the stored procedure, I simply removed this property.[/li]

[li]If for some reason you need to set this property for your insert, you can simply add the unnecessary parameter to the update stored procedure (though you won’t really be using it there!).[/li]
[/ul]


The third and fourth issues above are related : I.e., Values not being passed to the stored procedure. The problem was that I didn’t need to display all fields in my form, but needed to pass them to the stored procedure (ie., the PrimaryKey field and the Old values for comparison).
[ul]
[li]I created a hidden field for each parameter I needed to pass, and[/li]

[li]Changed the Parameter to a ControlParameter.[/li]

[/ul]
Naturally, this initially resulted in an error:
“Could not find control 'FieldName' in ControlParameter 'ParameterName'.”
This was due to the way I was referencing it. Since the Hidden control was a child control of the FormView, it needed to be referenced like this:

ControlID ="FormView1$HiddenField4"

Not like this:

ControlID ="HiddenField4"

Working Form View and SqlDataSource:
Code:
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
        <asp:FormView DefaultMode="Edit" ID="FormView1" runat="server" CellPadding="4" 
            DataKeyNames="AreaId" DataSourceID="SqlDataSource1" ForeColor="#333333">
            <EditItemTemplate>
                Name:
                <asp:TextBox ID="NameTextBox" runat="server" Text='<%# Bind("Name") %>' />
                <br />
                Description:
                <asp:TexatBox ID="DescriptionTextBox" runat="server" 
                    Text='<%# Bind("Description") %>' />
                <br />
                ParentId:
                <asp:TextBox ID="ParentIdTextBox" runat="server" 
                    Text='<%# Bind("ParentId") %>' />
                <br />
                TypeId:
                <asp:TextBox ID="TypeIdTextBox" runat="server" Text='<%# Bind("TypeId") %>' />
                <br />
                Enabled:
                <asp:CheckBox ID="EnabledCheckBox" runat="server" 
                    Checked='<%# Bind("Enabled") %>' />
                <br />
 [COLOR=brown]
<asp:HiddenField ID="HiddenField6" runat="server" Value='[COLOR=black]<%# Bind("AreaId") %>[/color]' />
<asp:HiddenField ID="HiddenField1" runat="server" Value='[COLOR=black]<%# Eval("Name") %>[/color]' />
<asp:HiddenField ID="HiddenField2" runat="server" Value='[COLOR=black]<%# Eval("Description") %>[/color]' />
<asp:HiddenField ID="HiddenField3" runat="server" Value='[COLOR=black]<%# Eval("ParentId") %>[/color]' />
<asp:HiddenField ID="HiddenField4" runat="server" Value='[COLOR=black]<%# Eval("TypeId") %>[/color]' />
<asp:HiddenField ID="HiddenField5" runat="server" Value='[COLOR=black]<%# Eval("Enabled") %>[/color]' />[/color]
                <asp:LinkButton ID="UpdateButton" runat="server" CausesValidation="True" 
                    CommandName="Update" Text="Update" />
                &nbsp;<asp:LinkButton ID="UpdateCancelButton" runat="server" 
                    CausesValidation="False" CommandName="Cancel" Text="Cancel" />
            </EditItemTemplate>
            
            <PagerStyle BackColor="#FFCC66" ForeColor="#333333" HorizontalAlign="Center" />
            <HeaderStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
        </asp:FormView>
        <asp:SqlDataSource ID="SqlDataSource1" runat="server" 
            ConnectionString="<%$ ConnectionStrings:connString %>" 
            [COLOR=red]SelectCommand[/color][COLOR=blue]="SELECT AreaId, Name, Description, ParentId, TypeId, Enabled, 0 AS Error, '' AS Message FROM Areas WHERE (AreaId = 2)" [/color]
            UpdateCommand="editArea" UpdateCommandType="StoredProcedure">
[COLOR=brown]
            <UpdateParameters>
                <asp:ControlParameter ControlID="[COLOR=blue]FormView1$HiddenField6[/color]" Name="AreaId" Type="Int32" />
                <asp:Parameter Name="Name" Type="String" />
                <asp:Parameter Name="Description" Type="String" />
                <asp:Parameter Name="ParentId" Type="Int32" />
                <asp:Parameter Name="TypeId" Type="Byte" />
                <asp:Parameter Name="Enabled" Type="Boolean" />
                <asp:ControlParameter ControlID="[COLOR=blue]FormView1$HiddenField1[/color]"  Name="original_Name" Type="String" />
                <asp:ControlParameter ControlID="[COLOR=blue]FormView1$HiddenField2[/color]"  Name="original_Description" Type="String" />
                <asp:ControlParameter ControlID="[COLOR=blue]FormView1$HiddenField3[/color]"  Name="original_ParentId" Type="Int32" />
                <asp:ControlParameter ControlID="[COLOR=blue]FormView1$HiddenField4[/color]"  Name="original_TypeId" Type="Byte" />
                <asp:ControlParameter ControlID="[COLOR=blue]FormView1$HiddenField5[/color]"  Name="original_Enabled" Type="Boolean" />
                <asp:Parameter Direction="Output" Name="Error" Type="Boolean" />
                <asp:Parameter Direction="Output" Name="Message" Type="String" [b][COLOR=red]Size="255"[/color][/b] />
            </UpdateParameters>
[/color]
        </asp:SqlDataSource>

One thing to note about the above code is that the <asp:parameter> tags that add parameters which have corresponding bound controls in the form are completely superfluous since ALL selected fields that are bound are used as parameters for custom stored procedures anyway (whether you want to or not)!

As a final note. I should mention that in this entire nightmare I learned that you will need to set the Size property on parameters with certain datatypes such as Strings. I don’t remember what errors are related to this, but just keep that in mind as something to look for when you have problems executing a stored procedure from this miserable FormView control.

I hope this helps others find the solution more quickly than I did, as I wouldn’t wish what I went through on my worst enemy.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top