Preventing empty strings becoming NULL in asp.net dynamic-data - asp.net

I have a standard ASP.NET 4 Dynamic Data site (using Linq to SQL).
In my SQL-Server database I have hundreds of varchar fields that are set to NOT NULL, but have a default value of an empty string. They should never be NULL, but they may have an empty string as content.
When editing these fields on the dynamic data site, the internal logic sees the field as NOT NULL and somewhere between TextBox1.Text (which is an empty string) and calling the UPDATE sql it sets the value to NULL and they update fails.
I can see the System.Web.DynamicData.MetaColumn has a property 'ConvertEmptyStringToNull' but is is read-only.
What can I do to prevent the empty string becoming NULL without having to change properties for all the hundreds of fields?

Do you have a single procedure for calling your database?
If so you can check the fields values here, or just append a blank string to each value.

In FieldTemplates/Text_Edit.ascx.cs change the behavior for strings, first remove the
validators because they prevent the form from being submitted:
protected void Page_Load(object sender, EventArgs e) {
TextBox1.MaxLength = Column.MaxLength;
if (Column.MaxLength < 20)
TextBox1.Columns = Column.MaxLength;
TextBox1.ToolTip = Column.Description;
if (Column.IsString)
{
this.Controls.Remove(RequiredFieldValidator1);
this.Controls.Remove(RegularExpressionValidator1);
this.Controls.Remove(DynamicValidator1);
}
else
{
SetUpValidator(RequiredFieldValidator1);
SetUpValidator(RegularExpressionValidator1);
SetUpValidator(DynamicValidator1);
}
}
The piece of code that converts the empty string to NULL is somewhere in the ConvertEditedValue method, so skip that for strings:
protected override void ExtractValues(IOrderedDictionary dictionary)
{
if (Column.IsString)
{
dictionary[Column.Name] = TextBox1.Text;
}
else
{
dictionary[Column.Name] = ConvertEditedValue(TextBox1.Text);
}
}
Now you can update tables with empty strings, the problem of course is now you can set empty strings for all varchar fields not only the ones with a default value.
I don't see anywhere in the Linq to SQL or EF datamodels where I can find out about my SQL-Server default value. There is a property DefaultValue but it is always NULL.

Since you wish to set the default value (empty String) in the database and not in the application consider using metadata on the columns in question to default to the database's initialization:
[Column(IsDbGenerated = true, UpdateCheck = UpdateCheck.Never, AutoSync=AutoSync.Never)]
public object MyColumn { get; set; }

Related

Getting the current record of the lookup table

I need to get the value from a lookup field and need to auto-write this value to another string field. I used Modified field event to auto-populate string fields but when it comes to lookup I cannot get the value. I am dealing with this for 3 days. I would be really grateful if anyone can help...
I used this code to populate sting fields. And there needs to be field 3 which is lookup.
[
FormDataFieldEventHandler(formDataFieldStr(InventSite, InventSite, Field1), FormDataFieldEventType::Modified),
FormDataFieldEventHandler(formDataFieldStr(InventSite, InventSite, Field2), FormDataFieldEventType::Modified)
]
public static void Field1_OnModified(FormDataObject sender, FormDataFieldEventArgs e)
{
// get the form DataSource
FormDataSource dataSource = sender.datasource();
// get current record
InventSite inventSite = dataSource.cursor();
// contatenate string values
str details = strFmt("%1, %2", inventSite.Field1, inventSite.Field2);

SQL statement's placeholders that is not replaced leads to "Cannot update '#columnName'; field not updateable"

I'm writing some code updating database with a SQL statement that has some placeholders . But it doesn't seem to update these placeholders.
I got the following error:
Cannot update '#columnName'; field not updateable
Here is the method:
public void updateDoctorTableField(string columnName, string newValue, string vendorNumber) {
sqlStatement = "update Doctor set #columnName = #newValue where `VENDOR #` = #vendorNumber;";
try {
_command = new OleDbCommand(sqlStatement, _connection);
_command.Parameters.Add("#columnName", OleDbType.WChar).Value = columnName;
_command.Parameters.Add("#newValue", OleDbType.WChar).Value = newValue;
_command.Parameters.Add("#vendorNumber", OleDbType.WChar).Value = vendorNumber;
_command.ExecuteNonQuery();
} catch (Exception ex) {
processExeption(ex);
} finally {
_connection.Close();
}
}
Not all parts of the query are parameterisable.
You can't parametrise the name of the column. This needs to be specified explicitly in your query text.
If this is sent via user input you need to take care against SQL Injection. In fact in any event it would be best to check it against a whitelist of known valid column names.
The reason the language does not allow for parameters for things like table names, column names and such is exactly the same reason why your C# program does not allow for substitution of variables in the code. Basically your question can be rephrased like this in a C# program:
class MyClass
{
int x;
float y;
string z;
void DoSomething(string variableName)
{
this.#variable = ...
}
}
MyCLass my = new MyClass();
my.DoSomething("x"); // expect this to manuipulate my.x
my.DoSomething("y"); // expect this to manuipulate my.y
my.DoSomething("z"); // expect this to manuipulate my.z
This obviously won't compile, because the compiler cannot generate the code. Same for T-SQL: the compiler cannot generate the code to locate the column "#columnName" in your case. And just as in C# you would use reflection to do this kind of tricks, in T-SQL you would use dynamic SQL to achieve the same.
You can (and should) use the QUOTENAME function when building your dynamic SQL to guard against SQL injection.

ASP.NET 4 : Comparing the result set of an object and a string

I am retrieving the contents of a database using a object (its returning only one field) and then comparing it with a string which has been hashed with SHA1 .The code is as follows :
protected void Onbutton_click_login(object sender, System.EventArgs e)
{
var dbcontext = new PrepLicensingSolution2010.DAL.LicensingEntities1();
var user = dbcontext.getloginname(loginName.Text);
string HashedPassword = FormsAuthentication.HashPasswordForStoringInConfigFile(Password.Text, "sha1");
if (user.ToString() == HashedPassword)
{
Response.Redirect("faqs.aspx");
}
else
{
Response.Redirect("Default.aspx");
}
}
I put breakpoints and checked the data at each stage of the flow and the data in the object result set and in the string are the same but even then the conditional if fails
whats interesting is both the types being compared are of the type string and of the same value,so why is that that the redirect goes to the default.aspx page.
The image contains the data from the breakpoints
Any inputs would be great.
Thanks
Based on the screenshot, user.ToString() looks to be returning the string {System.Data.Objects.ObjectResult<string>}. This, of course, does not equal the hashed password.
Your problem is that the result of your getloginname call is a sequence of strings containing a single string, not a single string itself. The default implementation of ToString() simply returns the class name, and you can see it in the Value column for the "user" row in the screenshot. Changing your conditional statement to the following should fix it:
if (user.FirstOrDefault() == HashedPassword)

Saving CheckBox control values

I am using asp.net and I am trying to save checkbox values into a database. Multiple checkboxes may be entered into the same field in the database. So for instance I have two checkboxes with names "Comma" and "Hyphen" and if the user checks both of these then the database will store the values ',','-'. How do you do this?
thanks
To save multiple values into the same column I'd recommend using a flag enumeration. Here is a code sample using checkboxes.
If you really have to store the values in a comma-delimited format, might try something like this:
List<string> values = new List<string>();
if (cbComma.Checked) {
values.Add("','");
}
...
string result = values.ToArray().Join(",");
I'd agree with David Thomas Garcia's recommendation if you can save the value to the database using the enumeration (as an int or whatever was appropriate for the amount of options you'll have).
If that's not an option though, and you are bound to storing them in the database as a string of characters I'd do something like the following:
private void LoadData()
{
string dbVal = DataAccess.GetDbVal(); //Get your value from the database.
chkComma.Checked = dbVal.Contains(",");
chkDash.Checked = dbVal.Contains("-");
}
private void SaveData()
{
string dbVal = "";
if(chkComma.Checked)
dbVal += ",";
if(chkDash.Checked)
dbVal += "-";
DataAccess.SaveDbVal(dbVal); //Send the value of dbVal to your data layer to be saved.
}
Note that this does not include any separation of the values to be saved in the value stored in the database, but if you needed that you could use a List and do what David Thomas Garcia mentioned with the .ToArray().Join(","); in the SaveData() and in the LoadData() just make dbVal a List and the syntax doesn't need change.

Accessing Row Data In Telerik RadGrid (Server Side)

Ive no problems using Javascript to read the rows of a telerik radgrid component im using however I can seem to find anyway to access the row data server side when a postback occurs. Ive spent ages looking for solution but no luck.
Any pointers would be greatly appreciated.
Tony
You might want to look at the DataKeyValues property of the OwnerTableView object, which will let you access a collection of values that represent the fields in a given row. I use it during the EditCommand event handler, since a user of my site is directed to an edit page if they click on the link to edit a row in the grid, and I need to pass along certain info about the given row in the query string.
If this turns out to be what you need, you'll also need to define which fields should be made available through this property. To do that, look at the MasterTableView.DataKeyNames property in the property sheet for the grid. You basically specify a comma-delimited list of field names.
The server-side is the easy part:
GridItemCollection gridRows = TestGrid.Items;
foreach (GridDataItem data in gridRows)
{
ItemClass obj = (ItemClass)data.DataItem;
}
It's the client side part that I don't know! :[
private Int32 GetID()
{
foreach (Telerik.Web.UI.GridDataItem dataItem in radGrid.MasterTableView.Items)
{
if (dataItem.Selected == true)
{
Int32 ID = (Int32)dataItem.GetDataKeyValue("ID");
return ID;
}
}
throw new ArgumentNullException("Id Not found");
}
This is the one that works for me and uses the RadGrid.SelectedItems collection.
protected void LinkButton1_Click(object sender, EventArgs e)
{
List<Guid> OrderIdList = new List<Guid>();
foreach (GridDataItem OrderItem in this.RadGrid1.SelectedItems)
{
OrderIdList.Add(new Guid(OrderItem.GetDataKeyValue("OrderId").ToString()));
}
}
If you correctly created your controls in markup or page init for dynamic controls, then the RadGrid will properly restore state.
You can access the initial values that were loaded from the data source like this example below, provided you told the table view in question to keep the columns around in the data keys.
protected T GetInitialGridData<T>(GridDataItem item, string uniqueColumnName) {
item.ThrowIfNull("item");
uniqueColumnName.ThrowIfNullOrEmpty("uniqueColumnName");
return (T)item.OwnerTableView.DataKeyValues(gridItem.ItemIndex)(columnName);
}
If you are using a dynamic custom template column, and need to get to any values that may now be in their states, you can use:
protected string GetCustomTextBoxValue(GridDataItem item, string controlID) {
item.ThrowIfNull("item");
controlID.ThrowIfNullOrTrimmedEmpty("controlID");
return ((TextBox)item.FindControl(controlID)).Text;
}
private Int32 GetID()
{
foreach (Telerik.Web.UI.GridDataItem dataItem in radGrid.MasterTableView.Items)
{
if (dataItem.Selected == true)
{
// Int32 ID = (Int32)dataItem.GetDataKeyValue("ID");
Int32 ID =Convert.ToInt32(dataItem.GetDataKeyValue("ID"));
return ID;
}
}
}
//this will work

Resources