Can't get a value out an ASP.NET hidden field - c#

I am going through a YouTube video, to learn ASP.NET. I've gotten it to work for the most part, with a somewhat major caveat: I can't retrieve a value from a hidden field ID. Because of that, I don't have a value to send to a stored procedure to create or update.
The commented out line is the original statement. When I have that then execute
.ExecuteNonQuery, I get the following error:
Procedure or function 'ResourceCreateOrUpdate' expects parameter '#ResourceID', which was not supplied
When I try to display hfResourceID, I have nothing when trying to pass 0, for a create, or the ResourceID value, i.e. 1. That value however, doesn't get there. I know the stored procedure works because I can execute it in SQL Server Management.
I tried moving hfResourceID to a string, then a integer value, but I seem to be having problems creating the if/else: everything is marked as an error. When I hover over the lines, I get the following message, which pretty much leave me clueless:
"Embedded statement cannot be a declaration or labeled statement".
Would I be able to get any pointers on how to clear up my error, please? Thanks.
2017-10-13 # 10:38: code updated
<asp:HiddenField ID="hfResourceID" runat="server" />
protected void btnSave_Click(object sender, EventArgs e)
{
int intResourceID = 0;
bool boolIDHasValue = true;
try
{
intResourceID = Convert.ToInt32(hfResourceID.Value);
}
catch (Exception ex)
{
lblErrorMessage.Text = ex.Message;
boolIDHasValue = false;
}
if (boolIDHasValue)
{
if (sqlconnODRConnection.State == System.Data.ConnectionState.Closed)
sqlconnODRConnection.Open();
SqlCommand sqlcmdCreateOrUpdate = new SqlCommand("ResourceCreateOrUpdate", sqlconnODRConnection);
sqlcmdCreateOrUpdate.Parameters.AddWithValue("#ResourceID", intResourceID);
sqlcmdCreateOrUpdate.Parameters.AddWithValue("#Status", txtStatus.Text.Trim());
sqlcmdCreateOrUpdate.Parameters.AddWithValue("#FirstName", txtFirstName.Text.Trim());
sqlcmdCreateOrUpdate.Parameters.AddWithValue("#MiddleName", txtMiddleName.Text.Trim());
sqlcmdCreateOrUpdate.Parameters.AddWithValue("#LastName", txtLastName.Text.Trim());
sqlcmdCreateOrUpdate.Parameters.AddWithValue("#NickName", txtNickName.Text.Trim());
sqlcmdCreateOrUpdate.Parameters.AddWithValue("#Gender", txtGender.Text.Trim());
sqlcmdCreateOrUpdate.Parameters.AddWithValue("#USCitizen", txtUSCitizen.Text.Trim());
sqlcmdCreateOrUpdate.ExecuteNonQuery();
sqlconnODRConnection.Close();
string strResourceID = hfResourceID.Value;
Clear();
if (strResourceID == "")
lblSuccessMessage.Text = "Saved Successfully";
else
lblSuccessMessage.Text = "Updated Successfully";
FillGridView();
}
}

There are a few issues with the code you copied from that video. But here a snippet as to how it should be done. I've added 3 ways to convert from the HiddenField value to an actual int. Which one you use can depend on how you want to handle errors, 0 values etc. Not included in the snippet, but I like to check for IsNullOrEmpty while using Trim(), that gets rid of spaces that might make the value non-convertible if (!string.IsNullOrEmpty(hfResourceID.Value.Trim())).
int intResourceID = 0;
//this will try to convert but you won't see exeptions when failed
Int32.TryParse(hfResourceID.Value, out intResourceID);
//checks if there is a value in the hiddenfield, but throws yellow screen if not convertible
if (!string.IsNullOrEmpty(hfResourceID.Value))
{
intResourceID = Convert.ToInt32(hfResourceID.Value);
}
//catch an error when the value is not convertible, can be wrapped with !string.IsNullOrEmpty(hfResourceID.Value)
try
{
intResourceID = Convert.ToInt32(hfResourceID.Value);
}
catch (Exception ex)
{
//handle the error, can be seen with ex.Message
}
//if the hidden value is still 0 (for whatever reason) you might not want to execute the query
//so the next part will return and stop executing the rest of the code
if (intResourceID == 0)
{
return;
}
//update the database, using 'using' will ensure proper closure of the connection and disposing of any objects
using (SqlConnection connection = new SqlConnection("myConnectionString"))
using (SqlCommand command = new SqlCommand("ResourceCreateOrUpdate", connection))
{
//set the command type and add the parameters
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#ResourceID", SqlDbType.Int).Value = intResourceID;
try
{
//open the database connection and execute the command
connection.Open();
command.ExecuteNonQuery();
}
catch (Exception ex)
{
//there was an error opening the database connection or with the command, can be viewed with ex.Message
}
}

Your error regarding the embedded statement is because you a declaring
if (strResourceID == "")
int intResourceID = 0;
else
int intResourceID = (Convert.ToInt32(hfResourceID.Value));
When decalring a variable directly after an If or else then you need your curly brackets. So...
if (strResourceID == "")
{
int intResourceID = 0;
}
else
{
int intResourceID = (Convert.ToInt32(hfResourceID.Value));
}
As for your other issues I would need to see your client side code.

Take a look on ASP code, specifically the way you are setting hidden field value. I guess it is properly marked as runat=server but maybe some problem is going on in your asp.net code, try to debug client code by using: console.log function and see the output in your console browser.

Related

Is it bad practice to catch the "happy path" in an exception?

I have an SQL statement that checks to see if a value is in my database or not. I want to respond with the "happy path" if the value is not in the database.
I have found using DbDataReader (.NET) that if a SELECT query can't find the value it throws an exception - so my "happy path" ends up in the exception, not in the main try block.
I can always say "NOT IN" but I don't want to return all of the rows in the database that don't have the value - as this would return many thousands of results where as all I want is just a "no it is not here" type response.
public void wristbandScan(string barcode)
{
string query = "SELECT ticket FROM tickets WHERE
linked_barcode='" + barcode + "'";
ValidTicketEventArgs args = new ValidTicketEventArgs();
try
{
var queryResult = _dbRunner.queryThis(query);
args.Result = false;
args.Message = "WB already linked";
args.Barcode = barcode;
OnValidTicketEvent(args);
}
catch (Exception e)
{
this.updateWristband(barcode);
this.updateValid();
args.Result = true;
args.Message = "WB linked";
args.Barcode = barcode;
OnValidTicketEvent(args);
}
}
It feels wrong to me to catch the happy path in an error statement, but I do not want the lag associated with reading in all the rows with the NOT IN statement.
Is there a better way to do this or is this approach acceptable best practice?
Well, you don't have to fetch all the records to the client; let's extract a method for this. Assuming that you work with MS Sql:
public bool hasScanCode(string barcode) {
if (string.IsNullOrWhiteSpace(barcode))
return false;
//DONE: paramterize queries
string query =
#"SELECT ticket
FROM tickets
WHERE linked_barcode = #prm_BarCode";
using (var conn = new SqlConnection(connection_string_here)) {
conn.Open();
using (var q = new SqlCommand(conn, query)) {
//TODO: q.Parameters.Add is a better choice
q.Parameters.AddWithValue("#prm_BarCode", barcode.Trim());
using (var reader = q.ExecuteReader()) {
// we read (fetch) at most 1 record
// if empty cursor - no record with given barcode
return reader.Read();
}
}
}
}
then we can use it:
public void wristbandScan(string barcode) {
bool result = hasScanCode(barcode);
ValidTicketEventArgs args = new ValidTicketEventArgs() {
Result = result,
Message = result ? "WB linked" : "WB already linked",
Barcode = barcode,
};
OnValidTicketEvent(args);
}
Please, remember - exceptions are for exceptional situations. Exceptions are very slow (stack unrolling wants resources); they are not readable - catch, in fact, works as a notorious goto; they are dangerous - in your current code you catch too many exceptions: e.g. AccessViolationException if it's thrown somewhere within dbRunner.queryThis will be efficiently masked.
Create and call a StoredProcedure which can to handle the empty situation and return no rows instead of an exception.
Then handle the no rows scenario outside the try/catch.

procedure or function spAddStudent has too many arguments specified

I am using visual studio 2010 ultimate with SQL Server 2012, When I click save button first time it works fine, but after changing values it shows above mentioned exception. I m failed to solve this problem. please help me.
Thanks
Abdul Muttalib
public int AddStudent(StudentManager studentManager)
{
try
{
sqlCom.Connection = sqlCon;
sqlCon.Open();
sqlCom.CommandType = CommandType.StoredProcedure;
sqlCom.CommandText = "spAddStudent";
sqlCom.Parameters.AddWithValue("#Name", studentManager.Name);
sqlCom.Parameters.AddWithValue("#Father", tudentManager.Father);
sqlCom.Parameters.AddWithValue("#Gender", tudentManager.Gender);
sqlCom.Parameters.AddWithValue("#Religion", studentManager.Religion);
sqlCom.Parameters.AddWithValue("#MotherTongue", studentManager.Tongue);
sqlCom.Parameters.AddWithValue("#BirthDate", studentManager.BrithDate);
sqlCom.Parameters.AddWithValue("#Class", studentManager.StudentClass);
sqlCom.Parameters.AddWithValue("#Section", studentManager.Section);
sqlCom.Parameters.AddWithValue("#Shift", studentManager.Shift);
sqlCom.Parameters.AddWithValue("#RollNo", studentManager.RollNo);
sqlCom.Parameters.AddWithValue("#Fee", studentManager.Fee);
sqlCom.Parameters.AddWithValue("#FatherOccupation", studentManager.FatherOccupation);
sqlCom.Parameters.AddWithValue("#FatherCNIC", studentManager.Cnic);
sqlCom.Parameters.AddWithValue("#AddWithValueressRes", studentManager.AddressRes);
sqlCom.Parameters.AddWithValue("#PhoneRes", studentManager.PhoneRes);
sqlCom.Parameters.AddWithValue("#PhoneOff", studentManager.PhoneOff);
sqlCom.Parameters.AddWithValue("#Mobile", studentManager.Mobile);
sqlCom.Parameters.AddWithValue("#PostalCode", studentManager.PostalCode);
sqlCom.Parameters.AddWithValue("#Email", studentManager.Email);
sqlCom.Parameters.AddWithValue("#OtherInfo", studentManager.OtherInfo);
int i = sqlCom.ExecuteNonQuery();
sqlCon.Close();
return i;
}
catch (Exception ex)
{
throw ex;
}
}
}
}enter image description here
You could resolve this by calling sqlCom.Parameters.Clear() at the start of AddStudent to prevent accumulating redundant parameters whenever the method is called.
Also, using AddWithValue is easy and common, but it can be problematic.

How can I pause a SQLCE Query until the Table it is querying is no longer being accessed elsewhere?

I have a method that queries a table for the count of its records. QA has discovered an "edge case" where if a particular operation is canceled in a particular order and speed (as fast as possible), the GUI "forgets" about the rest of the records in that table (the contents of the tables are uploaded to a server; when each one finishes, the corresponding table is deleted).
To be clear, this table that is having records deleted from it and then queried for count ("workTables") is a table of table names, that are deleted after they are processed.
What I have determined (I'm pretty sure) is that this anomaly occurs when a record from the "workTables" table is in the process of being deleted when the workTables table is queried for the count of its records. This causes an exception, which causes the method to return -1, which in our case indicates we should cuase the GUI to not display those records.
Is there a way to check if a table is in the process of having a record deleted from it, and wait until after that operation has completed, before proceeding with the query, so that it won't throw an exception?
For those interested in the specifics, this method is the one that, under those peculiar circumstances, throws an exception:
public int isValidTable(string tableName)
{
int validTable = -1;
string tblQuery = "SELECT COUNT(*) FROM ";
tblQuery += tableName;
openConnectionIfPossibleAndNecessary();
try
{
SqlCeCommand cmd = objCon.CreateCommand();
cmd.CommandText = tblQuery;
object objcnt = cmd.ExecuteScalar();
validTable = Int32.Parse(objcnt.ToString());
}
catch (Exception ex)
{
validTable = -1;
}
return validTable;
}
...and this is the method that deletes a record from the "workTables" table after the corresponding table has had its contents uploaded:
private void DropTablesAndDeleteFromTables(string recordType, string fileName)
{
try
{
WorkFiles wrkFile = new WorkFiles();
int tableOK = 0;
DataSet workfiles;
tableOK = wrkFile.isValidWorkTable(); // -1 == "has no records"
if (tableOK > 0) //Table has at least one record
{
workfiles = wrkFile.getAllRecords();
//Go thru dataset and find filename to clean up after
foreach (DataRow row in workfiles.Tables[0].Rows)
{
. . .
dynSQL = string.Format("DELETE FROM workTables WHERE filetype = '{0}' and Name = '{1}'", tmpType, tmpStr);
dbconn = DBConnection.GetInstance();
dbconn.DBCommand(dynSQL, false);
populateListBoxWithWorkTableData();
return;
} // foreach (DataRow row in workfiles.Tables[0].Rows)
}
}
catch (Exception ex)
{
SSCS.ExceptionHandler(ex, "frmCentral.DropTablesAndDeleteFromTables");
}
}
// method called by DropTablesAndDeleteFromTables() above
public int isValidWorkTable() //reverted to old way to accommodate old version of DBConnection
{
// Pass the buck
return dbconn.isValidTable("workTables");
}
I know this code is very funky and klunky and kludgy; refactoring it to make more sense and be more easily understood is a long and ongoing process.
UPDATE
I'm not able to test this code:
lock (this)
{
// drop the table
}
...yet, because the handheld is no longer allowing me to copy files to it (I get, "Cannot copy [filename.[dll,exe] The device has either stopped responding or has been disconnected" (it is connected, as shown by ActiveStync))
If that doesn't work, I might have to try this:
// global var
bool InDropTablesMethod;
// before querying that database from elsewhere:
while (InDropTablesMethod)
{
Pause(500);
}
UPDATE 2
I've finally been able to test my lock code (copies of binaries were present in memory, not allowing me to overwrite them; the StartUp folder had a *.lnk to the .exe, so every time I started the handheld, it tried to run the buggy versions of the .exe), but it doesn't work - I still get the same conflict/contention.
UPDATE 3
What seems to work, as kludgy as it may be, is:
public class CCRUtils
{
public static bool InDropTablesMethod;
. . .
if (CCRUtils.InDropTablesMethod) return;
CCRUtils.InDropTablesMethod = true;
. . . // do it all; can you believe somebody from El Cerrito has never heard of CCR?
CCRUtils.InDropTableMethod = false;
UPDATE 4
Wrote too soon - the bug is back. I added this MessageBox.Show(), and do indeed see the text "proof of code re-entrancy" at run-time.
while (HHSUtils.InDropTablesMethod)
{
MessageBox.Show("proof of code re-entrancy");
i++;
if (i > 1000000) return;
}
try
{
HHSUtils.InDropTablesMethod = true;
. . .
}
HHSUtils.InDropTablesMethod = false;
...so my guess that code re-entrancy may be a problem is correct...

ODBCDataReader has rows but can not access data

So in C#, I have an ODBCDataReader that returns that it has rows, but when I try to access the data it returns an object not set to a reference of an object error. I tested the sql directly on the db and it does return a row without any nulls
OdbcDataReader results;
try
{
// Initialize & open odbc connection
using (OdbcConnection conn = new OdbcConnection(connectionString.ToString()))
{
conn.Open();
// Initialiaze odbc command object
using (OdbcCommand comm = new OdbcCommand(query.ToString(), conn))
{
results = comm.ExecuteReader();
}
}
}
catch
{
//detailed error messaging here (which does not get hit)
}
temp = results;
if (temp.HasRows == false)
{
//error messaging here does not get hit.
}
while (temp.Read())
{
try
{
//I attempted to access the data by creating an object array:
object [] objarray = new object[temp.FieldCount)
temp.GetValues(objarray); //this causes error
}
catch{ // error is caught here "object not set to a reference of an object" }
for (i = 0; i < temp.FieldCount; i++)
{
try
{
//I also attempted other ways to access the data including:
temp[i].ToString(); // this causes error
temp.GetInt32(i).ToString(); // this causes error
temp.GetName(i); //this causes error
}
catch
{
// error is caught here "object not set to a reference of an object"
}
}
}
You are using it outside the using blocks. Move the part where you use [results] inside the using blocks (immediately after the ExecuteReader() call) and you should be in a much better place.
I ran into this same issue. The problem in my case was that I was not binding my parameters correctly. I was binding using #:
SELECT * FROM MyTable WHERE MyField = #MyField
For some reason, this is valid in MySQL and doesn't produce an error, but will not return data. The solution was to bind using ?:
SELECT * FROM MyTable WHERE MyField = ?
Then in C# bind the parameters:
cmd.Parameters.AddWithValue("#MyField", myFieldValue);
Old question, but it's the first result on Google and unanswered. Hope it's helpful.

Web checkbox not providing value to function

I've got a weird issue that I can't seem to figure out. I created a web component for a commercial application I have running on a server. If I change the cbxGramEnabled.Checked to True or False the function runs OK and makes the change. However, if I leave the cbxGramEnabled.Checked the function doesn't update the DB.
The code that runs the component looks like this:
private void WriteToSQL( )
{
WriteEnableGram( _pkKey, cbxGramEnabled.Checked);
}
The cbxGramEnabled.Checked is a CheckBox on my custom component for the web app.
private void WriteEnableGram( int nPKkey, bool bChecked)
{
string szQuery = string.empty;
if (bChecked == true)
szQuery = "UPDATE dbo.CustomKeyAttr SET EnableGram = 1 WHERE pkCustomKeyAttr = " + nPKkey.ToString() + ";";
else
szQuery = "UPDATE dbo.CustomKeyAttr SET EnableGram = 0 WHERE pkCustomKeyAttr = " + nPKkey.ToString() + ";";
try
{
string szConString = #"Data Source=.\sqlexpress;Initial Catalog=MetricDB;User ID=webuser;Password=mypass;";
using (var Conn = new SqlConnection(szConString))
{
Conn.Open();
using (SqlCommand dbQuery = new SqlCommand(szQuery, Conn))
{
dbQuery.ExecuteNonQuery();
}
}
}
catch (SqlException)
{
}
catch (Exception)
{
}
finally
{
cbxEnableGram.Text = szQuery; // at least display what the query is somewhere on the page....
}
}
First of all, let's assume the following is true:
A boolean value can be true; false or null (unassigned).
The checked property of the checkbox can have those values.
Let's also assume that
If cbxGramEnabled contains a reference to a Checkbox instance at runtime on that line of code, the value of checked can never be null unless there is some weird bug in its framework implementation. I'm assuming this is a .NET checkbox? Explanation: a reference exists only when the constructor of that object has finished running, and having set all the properties to a default value that is different from null.
Since, if the value of the checked property would be either true or false, the code would execute normally, as proven by your attempt with literal true/false values, we are sure that the actual value is null. Statement 2 proves that cbxGramEnabled does not contain an object reference at that point in your code.
Essentially, the variable cbxGramEnabled has no real value, it contains a null reference. The cause for that is that your code is executed before this checkbox has been created.
Typically in a web app, this happens when your page is still loading (creating the components) and your code is executing before the page has completely loaded. This may well be happening between round-trips to the server!! I'm fairly sure that is where your problem is....

Categories

Resources