Using TinyMCE with ASP.Net UpdatePanels
March 16, 2012
My WYSIWYG editor of choice is TinyMCE.
I have recently had a problem where the contents of an ASP.Net text box on a site (TextBox.Text) was empty on postback – Even though text was entered by the user. The text box in question was within an UpdatePanel. The solution is simple – On the button that fires the post back, add OnClientClick=”tinyMCE.triggerSave(false,true);” where tinyMCE is the ID of your TinyMCE instance.
LINQ2SQL – Updating Stored Procedures (VS2008)
October 6, 2011
I’m currently working on a project using LINQ2SQL with stored procedures. I quickly ended up with a problem that rang bells, remdinding me of when I last worked with LINQ2SQL and SPROCS (Some time back), that problem being that once a SPROC has been added to the DataContext, its not possible to (easily) update the output of it, or the signiture.
I remember my previous fix to this was to rename the stored procedure and re-add it (Deleting the old one from the DataContext). This works fine on smaller systems with 1-2 developers – Renaming a Stored Procedure on a larger system may not alwasy be an option.
So, here is a better fix for this scenario – Its not elegant, and still irritating, but it does work…
(Note: Only tested in Visual Studio 2008 – I dont know if this problem exists in Visual Studio 2010)
- Delete stored proc from DBML file
- Close DBML file
- Right click on DBML in solution explorer – Open with > XML Editor then Save it (No need to make any changes)
- Open DBML file as normal
- Right click on SPROC in server explorer > refresh (To ensure Visual Studio knows about the changes to your stored procedure)
- Drag and Drop SPROC to your DBML to re-add it with the new signature/return type
- Hoorah!
LINQ – Group by multiple columns, with join
September 22, 2011
In order to get data to drive a new report I was developing this morning, I needed a Group By query. I have done this before, but really could not remember the syntax, hence this post, for my furture reference, and hopefully helpful to others!
var result = (from tbl1 in YourDayaContext.Messages
join tbl2 in YourDayaContext.Table2 on tbl1.id equals tbl2.id
join tbl3 in YourDayaContext.Table3 on tbl2.id equals tbl3.id
group tbl1 by
new
{
tbl1.tbl1_Col1,
tbl1.tbl1_Col2,
tbl2.tbl2_Col1,
tbl3.tbl3_Col1,
} into g
where g.Count() > 1
select new
{
g.Key.tbl1_Col1,
g.Key.tbl1_Col2,
g.Key.tbl2_Col1,
g.Key.tbl3_Col1,
Quantity = g.Sum(tbl1 => tbl1.tbl1_Col1)
});
Probably worth mentioning at this stage that I changed the vae/table/column names in the code above from a working version to protect my database schema security – I have not compiled/tested the above.
Visual Studio 2008 – Remote Debugging
September 17, 2011
I was working on a project today which involved debugging a web service, being called from separate application which we also needed to debug at the same time (So we would workout what part of the system was playing up).
The client application was already setup to call the web service on our test server. We wanted to retain this in order to replicate the production environment as closely as possible. The test server did not have visual studio installed, also, we wanted to run the web service via IIS – Not Visual Studios built in web server.
To allow us to debug from my desktop PC, I enabled remote debugging on the test server, allowing us to attach to th IIS application pool process
Step-by-Step Walk Through…
- From the client machine, copy folder ‘Remote Debugger’ from C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ to the server at any convenient location
- Run the appropriate version (X86/x64) of the listener – ‘msvsmon.exe’ on the server, found in the ‘Remote Debugger’ folder – This needs to be run as Administrator (Right click, run as administrator)
When it runs, you should see the log, with the first line showing:
‘MSVMON started a new server named ‘username@servername’. Waiting for new connections’ - Your application will need to include PDB (Program Database) files – These include source file names, their lines and local variable names.
See http://www.wintellect.com/CS/blogs/jrobbins/archive/2009/05/11/pdb-files-what-every-developer-must-know.aspx for a full explaination)
If you are used to right clicking your project name and selecting publish to deploy your site/web project, be aware that this method will always compile a release build which will exclude the PDB files. Instead, you’ll need to use one of the following methods:A) ASP.Net Compilation Tool:
See http://msdn.microsoft.com/en-us/library/ms229863.aspxfor detailsB) Build in debug mode, and manually copy/ftp the files to the server. - You are now ready to commence debugging. Open Visual Studio on your client machine, select ‘Debug’ > ‘Attach to Process’. Transport should be set to ‘Default’. Enter the server name (The server you ran msvsmon.exe on) in the Qualifier box and hit enter. You will notice this will be resolved to username@servername
- From the list of available processes, select W3WP.EXE (IIS Worker Process) and click ‘Attach’. You will recieve a security warning – Click ‘Attach’
- If all has gone well, you should now be able to set a break point in your code, run the code (By opening the web site at its server/remote address) and see he break point hit.
Worth Mentioning…
- In our scenario, we were running Windows 7 client machines connected to Windows Server 2008 Web Server
- The code on the server needs to be the same as the code you arer using to debug – Otherwise line numbers will likely be out of sync, making debugging very difficult!
- Debug symbols (.PDB Files) are stored in your app at: \obj\Debug
Trouble shooting…
(Only 1 suggestion right now – I’ll add to this if/when I discover others!)
- If you cannot see W3WP.EXE in the ‘Attach to process’ dialog, ensure you have:
- Ticked ‘Show processes from all users’
- Ticked ‘Show processes in all sessions’
- Ran (Browsed to) the application at least once (Or indeed, any app on the server) to load the worker process
Lambda Loop
August 31, 2011
Very quick tip…instead of a ‘traditional’ For Each loop:
foreach (String s in stringList)
{
LabelOutput.Text += s + "<br/>";
}
Consider a Lambda loop:
stringList.ForEach(s => LabelOutput.Text += s + "<br/>")
The result is less code, more readable code (IMHO!) and having tested both with 10,000 strings in a list, it seems there is no impact on performance.
You can of course filter the list using a Lambda expression, still on the 1 line of code:
stringList.Where(s => s.Contains(foo)).ForEach(s => LabelOutput.Text += s + "<br/>")
Update data following control event in GridView
June 11, 2011
This week, the request for an additional administration screen one of the web based LOB applications I manage/develop gave me the opportunity to build an elegant, user friendly interface. The functionality required was the ability to update one property of a very simple object, with a very low chance of needing to make updates to other properties in future. It is also worth bearing in mind that the collection of objects concerned is minimal and fixed in quantity (Less than 30 objects).
I decided the best way to achieve this would be to present the objects in a GridView, with no paging, on the basis that it would be easiest for the user if they could see all objects on one screen, and that loading 30 or so objects in one hit would actually be less of a performance hit that the process of querying and displaying paged data. I also wanted all functionality to be provided from within the GridView – Again due to simplicity of the objects concerned – Of which we only need to update one property.
So we have a GridView with three columns:
- Bound Column: Object Reference
- Bound Column: Object Name
- Template Column: Containing a DropDownList, set to AutoPostBack
It is worth mentioning at this stage that all pages main content area are contained within AJAX partial update panels. I dislike AutoPostBack in general, it can make the application seem clunky and slow, although with efficient coding and correct use of AJAX can of course achieve quite the opposite effect/result.
So, the user visits the page, locates the record they wish to update (listed in alphabetical order) and changes the value of the DropDownList, which should then update the associated record/object.
There are two potentially challenging aspects to this setup:
1) How to fill the DropDownList with appropriate values, and select the correct value for each row
(To show the current value, before and after DropDownList change event).
To achieve this, we need to:
- Get a reference to the DropDownList associated with each record/object
- Add appropriate ListItems
- Ensure that the current value is selected
protected void GridViewFoo_RowDataBound(object sender, GridViewRowEventArgs e)
{
DropDownList dropDownListFoo = null;
// We are only interested in DataRows (Not headers/footers)
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Get a reference to the DropDownList
dropDownListLeague = (DropDownList)e.Row.Cells[1].Controls[1];
// Retrieve the value of the property that will determine the value to set the DropDownList to
Boolean fooMyObjValue = Boolean.Parse(DataBinder.Eval(e.Row.DataItem, "PropertyName").ToString());
// Define the values for the DropDownList
ListItem liYes = new ListItem("Yes", "Y");
ListItem liNo = new ListItem("No", "N");
// Depending on the value of the Object proeprty, set the appropriate ListItems selected property
if (fooMyObjValue == true)
{
liYes.Selected = true;
}
else
{
liNo.Selected = true;
}
// Add the items to the DropDownList
dropDownListLeague.Items.Add(liYes);
dropDownListLeague.Items.Add(liNo);
}
}
2) How to update the Object when the user changes the value, via the DropDownList
For this, I made use of the DataKeyNames property of the GridView – Our objects have an ID property – This is the unique identifier for each one, so its simply a case of telling the GridView what property of its Data Bound collection is the key:
<asp:GridView ID="GridViewFoo" runat="server" onrowdatabound="GridViewFoo_RowDataBound" DataKeyNames="ID"...
The DropDownList’s SelectedIndexChanged event is wired up, and runs the following code:
protected void DropDownListFoo_SelectedIndexChanged(object sender, EventArgs e)
{
// Get the calling DropDownList
DropDownList dropDownListFoo = (DropDownList)sender as DropDownList;
// Get the GridViewRow the DropDownList was called from
GridViewRow row = (GridViewRow)dropDownListLeague.NamingContainer as GridViewRow;
// Get the DataKey of the row - Which is our objects 'ID' property
// because we set the GridViews DataKeyNames property to 'ID'
int id = (int)GridViewFoo.DataKeys[row.RowIndex].Value;
// Now we have the ID, we can of course call a method in our BLL (Or run a SQL query if your architecture is not quite ideal!) to update our object property to the new value, derived from dropDownListFoo.SelectedValue
Debug Pre-Processor Directives
March 29, 2011
If you use any of the methods in the Debug class (such as Debug.Write), you should be aware that these statements will still be in your compiled code (release or debug build) and will still run on your production server.
It could be that such statements make a negligable difference to the performance of your code, but imagine the scenario where the developer wants to check the sum or 3 or 4 items, or worse still a string concatenation to show maybe 3 or 4 variables, within a Loop – This is additional processing that is completely needless!
To avoid this, I use Pre-Processor Directives – Don’t worry about the name, like alot of development related speak they sound scary and complicated, when in fact its a very simple thing to do in order to avoid all they needless processing…
// The first line in your code, define the DEBUG symbol
#define DEBUG
// Then, where ever you use the DEBUG class, wrap your code in an if statement as follows
#if DEBUG
DateTime startTime = DateTime.Now;
Debug.WriteLine("ProcessRequest() Commenced: " + startTime);
#endif
The code within the #if/#endif will be excluded from the compiled code, except of course when you are debugging.
This is a much more elegant solution than having these statements run in release code, or having to strip them all out before a release build.
Highlighting ListItems in a DropDownList
March 17, 2011
I’ve just completed adding functionality to a system that allowed the user to select a persons name from a DropDownList. The list was structured hierarchically, in that each person in the list was shown indented under his/her manager. To make the structure clearer, I wanted to highlight managers in a different colour. Heres how I did it:
In the loop, where I was creating ListItems for each person (Which were than added to the DropDownList) I added an attribute to the ListItem to apply a CSS class:
Method 1
When items are explicitally added to the DropDownList
foreach (DataRow drSomeRow in someDataTable.Rows)
{
String name= drSomeRow ["Name"].ToString();
String id = drSomeRow ["ID"].ToString();
ListItem liPerson = new ListItem(name, id);
liPerson.Attributes.Add("class", "highlightedListItem");
// Note: In this example, the CSS class is applied to all items in the list
// In reality you would probably wrap this line in an if statement, checking a record value
SomeDropDownList.Items.Add(liPerson);
}
Method 2
DropDownLists that are DataBound to a list of objects/DataTable etc?
Often, DropDownLists (and other DataBound controls) will be bound to a DataSource, rather than populated item by item as in example 1 above. In this case, we need to loop the items in the DropDownList after they have been added. Note that this method does depend upon either:
A) Having some way of determining whether or not the ListItem should be highlighted, based on either the Value or Text properties
Or
B) Making an external call passing either the Text or Value propertie values as a key to retrieve some other information
(I would suggest steering clear of B as this potentially means a database/webservice call for each item in your list – Inefficient and slow!
foreach (ListItem liPerson in DropDownListTeams)
{
if liPerson.Value.Contains(SomeValue) {
liPerson.Attributes.Add("class", "highlightedListItem");
}
}
Sorting a DataTable
January 13, 2011
Just a quick tip this one. To sort a DataTable…
- Clone the Unsorted DataTable
- Generate a DataRow array, from the unsorted DataTable using .Select, specifying the search criteria (The first argument is the select criteria, which I have left Null so we get all rows)
- Loop the DataRow array, importing the rows into the new table
DataTable dtSorted = dt.Clone();
DataRow[] dataRowsSorted = dtUnSorted.Select(null, "PercentSurveysCompleted ASC");
foreach (DataRow dataRow in dataRowsSorted)
{
dtSorted.ImportRow(dataRow);
}
LINQ Error – Row not found or changed
December 15, 2010
Just called an update on a Linq object and instead of a nicely updated SQL record, I got an error:
Row not found or changed
Why? I had just added a new property to the table I was updating – I did this manually, instead of deleting and re-adding the table so I didnt lose all the changes I have made to the object since first dragging it onto the design surface, which is fine – Although I forgot to check the nullable setting of the SQL column – The mimatch (SQL column nullable, data context object property NOT nullable) caused the error – As soon as these were set correctly, all was good!
Row not found or changed - Not exactly a very useful/relevent error message!
