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....
Related
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.
I'm trying to return a string though a Getter, the string is obtained from a DataRead object which loops through the mysql query. The problem is that, upon load, the string does not get loaded onto the main form's label, it returns an empty string and if I assign a string to the variable upon declaration, it returns that to my main form. Here's the code:
string text;
public string Text { get { return text; } }
public void DBConn()
{
MySqlConnection conn = new MySqlConnection(connStr);
DataSet ds = new DataSet();
MySqlDataReader reader = null;
try
{
// connection to DB
reader = cmd.ExecuteReader();
if (reader != null && reader.HasRows)
{
while (reader.Read())
{
text = reader["string1"].ToString() + " " + reader["string2"].ToString() + " " + reader["string3"].ToString();
}
}
}
// try, catch. conn.close()
}
The reader is assigning the values onto text just fine, but outside of the while, the value is not assigned to the globally declared variable, it seems to get destroyed as soon as it leaves the loop. Can anyone please help?
Thank you.
Thank you to those who helped me find the solution to the problem described. As some of you kindly explained (and I was lacking the knowledge to understand at first until a lot of research was done), the issue turned out to be a problem with my Main form being in a different instance from the first class that calls upon the class that has the Getter in it. I know now I should have mentioned all of these details in the original post, I apologize to those of you who tried to understand from a small piece of code. After a lot of research on Instances, the solution I came to was to first, create a class that holds static Getters and Setters public static string Text { set; get; } (this was how I wanted it for easy access from other classes) this helps in making them accessible from all instances, it might not be the best solution especially on OOP - During my research I read somewhere that using Setters and Getters is a waste of time and not the best practice for programmers, that it is best to encapsulate but because I am still very fresh I will look up how to do that later.
Thank you guys again.
I know what is causing the Redirect loop in my code, I am just not sure how to fix it. First, my code.
switch (Request.QueryString["Error_ID"])
{
case "1":
// Error Code 1 is when a user attempts to access the Admin section and does not have rights to.
MultiView1.ActiveViewIndex = 1;
break;
case "2":
// Error Code 2 is when a user is not currently Active.
MultiView1.ActiveViewIndex = 2;
break;
default:
// Default is View Index 0 for default access.
MultiView1.ActiveViewIndex = 0;
break;
}
// Get current username.
string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
// Test to see if user is Active.
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["HSEProjRegConnectionString1"].ConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("SELECT [active] FROM [tbl_Person] WHERE username LIKE #username", conn))
{
cmd.Parameters.AddWithValue("#username", "%" + userName + "%");
var res = cmd.ExecuteScalar();
bool registeredAndActive = (bool)res;
if (registeredAndActive)
{
// Active Condition. The DEFAULT in SWITCH() will take care of displaying content.
}
else
{
// !Active Condition. Shows an alternative version of the default page where the user is told they do not have access.
Response.Redirect("default.aspx?Error_ID=2");
}
}
The point of the code is to first check for a Query String in the SWITCH() method in case one is provided on a later page. Then it grabs current AD username logged in with, and then checks a user database to see if the user is marked Active. If so, it does nothing as it will allow the page to load as normal. If not, then it redirects to the same page but appends an Error_ID so that I can display a different View saying that the user does not have access. I am pretty sure this is where the redirect loop is coming from. Does anyone have any ideas on how I can eliminate Redirect Loop? I tried doing a Request.Url.ToString() and then a !var.Contains to do the Redirect, but I couldn't make that work either.
EDIT: I should note that I am interested to hear if anyone has any alternatives to Response.Redirect(). It works, but originally, I was using Response.End() and that didn't allow any code to run so came up with using Response.Redirect() and a QueryString to do what I wanted.
You are testing if your user is active twice. Also, in the second check, you keep redirecting the page to itself, which keeps doing the checks.
Your first check is here:
switch (Request.QueryString["Error_ID"])
{
(...)
case "2":
// Error Code 2 is when a user is not currently Active.
MultiView1.ActiveViewIndex = 2;
break;
(...)
and your second check is here:
if (registeredAndActive)
{
// Active Condition. The DEFAULT in SWITCH() will take care of displaying content.
}
else
{
// !Active Condition. Shows an alternative version of the default page where the user is told they do not have acces.
Response.Redirect("default.aspx?Error_ID=2");
}
So the second check redirects the page to itself, and it keeps looping forever.
The easiest way to fix this, IMHO, is to not check if your current user is active if your error code is "2", i.e. you could either:
1) Stop the page execution if Error_ID is 2, i.e. change the first check to:
case "2":
// Error Code 2 is when a user is not currently Active.
MultiView1.ActiveViewIndex = 2;
Response.End(); // <--- this will stop the execution before reaching the first block
break;
2) Don't redirect the page again, if Error_ID is 2, i.e. change your second check to:
if (registeredAndActive)
{
// Active Condition. The DEFAULT in SWITCH() will take care of displaying content.
}
else
{
// !Active Condition. Shows an alternative version of the default page where the user is told they do not have acces.
if (MultiView1.ActiveViewIndex != 2) { // check if the page has already been redirected
Response.Redirect("default.aspx?Error_ID=2");
}
}
IMHO, solution 2 seems to be the cleanest and most elegant of the two
You only need to perform the database check if the query string value (Error_ID) is not 1 or 2. The way the logic is written, you will always check for whether or not the user is active and if they are not, then it will keep sending the Error_ID=2 query string value to the page and you will be stuck in a loop. I would recommend separating out the logic to test for the query string into a separate method and have it return a Boolean of whether or not to attempt to query the database for the Active value.
How about doing something like this:
if(MultiView1.ActiveViewIndex != 2)
{
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["HSEProjRegConnectionString1"].ConnectionString))
{
conn.Open();
using (SqlCommand cmd = new SqlCommand("SELECT [active] FROM [tbl_Person] WHERE username LIKE #username", conn))
{
cmd.Parameters.AddWithValue("#username", "%" + userName + "%");
var res = cmd.ExecuteScalar();
bool registeredAndActive = (bool)res;
if (registeredAndActive)
{
// Active Condition. The DEFAULT in SWITCH() will take care of displaying content.
}
else
{
// !Active Condition. Shows an alternative version of the default page where the user is told they do not have acces.
Response.Redirect("default.aspx?Error_ID=2");
}
}
}
}
I'm making a rather "simple" piece of software and at the moment I'm working with one table in my database and reading from the database works and now I was trying to implement inserting into the database, which seems to work as long as the program is running, but when I stop the program (stop debugging in VS) and launch it again, the rows don't seem to be in the database (already checked the .mdf database itself for the rows but they can't be found).
This is the piece of code:
public void saveKlant(klant nieuweKlant)
{
KlantGegevens newKlant = new KlantGegevens();
newKlant.klantNaam = nieuweKlant.naam;
newKlant.klantStraat = nieuweKlant.straat;
newKlant.klantPostcode = nieuweKlant.postcode;
newKlant.klantHuisNummer = nieuweKlant.huisnummer;
newKlant.klantGSM = nieuweKlant.gsm;
newKlant.klantTel = nieuweKlant.telnummer;
newKlant.klantGebDatum = nieuweKlant.gebDatum;
newKlant.klantEmail = nieuweKlant.email;
using (kapsalonEntities context = new kapsalonEntities())
{
try
{
context.KlantGegevens.AddObject(newKlant);
int test = context.SaveChanges();
}
catch
{
throw new InvalidOperationException("het object kon niet toegevoegd worden");
}
}
}
"test" equals 1 (so context.SaveCHanges() = 1) when running the program.
what would be the reason for the data to not be added persistently? since I do use a Context.SaveChanges()?
Thanks in advance.
It looks like you didn't check of the property where the database each time copies himself toi the debug directory. That's why you always get your default data again. Set the property to "if newer"
I'm creating a custom workflow activity in VS2010 targeting .NET 3.5. The DLL is actually being used in a Microsoft System Center Service Manager custom workflow, but I don't think that is my issue.
I have a public string property, that the user types in the string of what the activity should use. However, when the WF runs, it errors out 'value cannot be null'. I want to target if it is my code or something else.
When we drag my custom activity onto the designer, I'm able to type in the text of the string on the designer for that property.
public static DependencyProperty ChangeRequestStageProperty = DependencyProperty.Register("ChangeRequestStage", typeof(String), typeof(UpdateChangeRequestStage));
[DescriptionAttribute("The value to set the ChangeRequestStage Property in the ChangeRequest Extension class.")]
[CategoryAttribute("Change Request Extension")]
[BrowsableAttribute(true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public String Stage
{
get { return ((String)(base.GetValue(UpdateChangeRequestStage.ChangeRequestStageProperty))); }
set { base.SetValue(UpdateChangeRequestStage.ChangeRequestStageProperty, value); }
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
EnterpriseManagementGroup emg = CreateEMG();
//System.WorkItem.ChangeRequest Extension - ClassExtension_928bec0a_cac4_4a0a_bd89_7146c9052fbe
ManagementPackClass mpcChangeRequest = emg.EntityTypes.GetClass(new Guid("8c6c6057-56ad-3862-47ec-dc0dde80a071"));
//System.WorkItemContainsActivity Relationship Class
ManagementPackRelationship workItemContainsActivityRelationship = emg.EntityTypes.GetRelationshipClass(new Guid("2DA498BE-0485-B2B2-D520-6EBD1698E61B"));
EnterpriseManagementObject changeRequest = null;
//Loop thru each emo (Change Request in this case), and assign it. There will never be more than 1 emo returned
foreach (EnterpriseManagementObject obj in emg.EntityObjects.GetRelatedObjects<EnterpriseManagementObject>(executionContext.ContextGuid, workItemContainsActivityRelationship, TraversalDepth.OneLevel, ObjectQueryOptions.Default))
{ changeRequest = obj; }
EnterpriseManagementObjectProjection emop = new EnterpriseManagementObjectProjection(changeRequest);
if (emop != null)
{ emop.Object[mpcChangeRequest, "ChangeRequestStage"].Value = Stage; }
emop.Commit();
return base.Execute(executionContext);
}
Since it is getting a 'value cannot be null' error, I'm guessing it's on this line:
emop.Object[mpcChangeRequest, "ChangeRequestStage"].Value = Stage;
I'm going to test and see if hardcoding a value works or not. Any ideas?
enter code here
try this
if (emop != null && emop.Object[mpcChangeRequest, "ChangeRequestStage"] != null)
emop.Object[mpcChangeRequest, "ChangeRequestStage"].Value = Stage
I didn't want to leave this question wide open, so I'm updating it as to how I resolved this (a long time ago).
Rather than working with an EnterpriseManagementObjectProjection (emop), I worked with a standard EnterpriseManagementObject (emo). From there, I was able to follow a similar format from above:
ManagementPackClass mpcChangeRequest = emg.EntityTypes.GetClass(new Guid("8c246fc5-4e5e-0605-dc23-91f7a362615b"));
changeRequest[mpcChangeRequest, "ChangeRequestStage"].Value = this.Stage;
changeRequest.Commit();