.Net ramblings
# Monday, 08 November 2004
Asp.Net DataGrid PageIndexChanged not working

i have an asp.net custom server control (deriving from a datagrid) and it has built in paging, sorting and databinding.  i ran into a weird problem, and thanks to Rick Strahl's post on http://west-wind.com/weblog/posts/211.aspx i was able to get it working.  Read that page first because there are many solutions posted for this weird error.

i'm using regular paging, and the next button works fine (all the time, for multiple pages), but if i click previous then a dud postback happens and the pageIndexChanged event doesn't fire.  i'm 100% sure that the eventhandler is hooked up, it just doesn't fire.  the solution in my case was to bind the datagrid in the control's PreRender method instead of in the OnInit method.  it just worked fine after doing this. 


Monday, 08 November 2004 18:33:01 (GMT Standard Time, UTC+00:00)  #    Comments [0]  Asp.Net

# Wednesday, 03 November 2004
using the same WSE2 web service with 2 different policies..

did you know you can configure multiple policies for the same web service?  it's possible because endpoint uri's are case-sensitive, so you can have WebService1.asmx and WEBSERVICE1.asmx, which are treated as separate web services in the policyCache.config file. see the sample below:

<endpoint uri="http://localhost/winDB.asmx">
 <defaultOperation>
  <request policy="#username-token-signed" />
  <response policy="" />
  <fault policy="" />
 </defaultOperation>
</endpoint>

<endpoint uri="http://localhost/WINDB.asmx">
 <defaultOperation>
  <request policy="" />
  <response policy="" />
  <fault policy="" />
 </defaultOperation>
</endpoint>

the first one uses a username-token-signed policy for authentication.  clients who wish to use this policy must have a reference to the web service matching the case of the endpoint uri exactly. 

the second endpoint has no policy enforcements and this means even a non-WSE request can use the web service.

some WSE implementations, (especially custom username tokens..) will have a method like "checkAuth()" that every web method calls at the start to verify programattically that the message obeys the rules.  this method throws soap faults for any missing WSE elements in the message header.  in my case, i want to allow requests originating from the web server itself (.aspx pages using the web methods) to bypass the authentication checks, so i put the following lines of code at the top of my "checkAuth()" method to allow requests made on the same server to go through:

// allow local ws requests to bypass security
if(HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"].ToString() == "127.0.0.1")
  return;  // skip further checks

i could also invoke the web methods using the web service class directly, (not go through a web service proxy) because it's within the same assembly, but i'm sure there are circumstances where this approach may prove useful.  if you find any, post them here as a comment, i'd be interested to hear.  


Wednesday, 03 November 2004 17:43:16 (GMT Standard Time, UTC+00:00)  #    Comments [0]  Asp.Net

# Tuesday, 26 October 2004
TextBox.Focus() doesn't work within Form_Load

i have a windows form with a textbox inside a panel, and the following code doesn't work as expected:

private void WizardLoad(object sender, System.EventArgs e)
{
  this.txtUsername.Focus();
}

Thanks to someones post

i now know that the best way to do it is as follows:

this.ActiveControl = this.txtUsername;

It works!


Tuesday, 26 October 2004 12:06:57 (GMT Daylight Time, UTC+01:00)  #    Comments [1]  .Net Windows Forms

# Sunday, 10 October 2004
SQL Server - Access denied messages using Server=(local) with named instances

I'm developing a .net application that uses a sql server database.  i develop it on a desktop and a laptop, and i want to configure the app to use the local instance of sql server, rather than the named instances: LAPTOP\LAPTOP and DESKTOP\DESKTOP, because if the laptop is not on the network then it can't connect to any other db.  I tried connecting with the following connection string:

Server=(local); initial catalog=MyDB; UID=sa; PWD=whatever; 

but it didn't work,  "SQL Server does not exist or access denied".  I found out after a lot of searching that this is because i had installed a 'named instance' of sql server rather than the 'default instance'.  This is a tick box during the sql server install.  I also found out that its easy to change it back to a default instace.  all you do is run the sql server install again, and choose the default instance. you then have 2 sql server installations (they don't conflict).  if you look in the add/remove programs, there are 2 entries, one 'microsoft sql server' and another 'microsoft sql server (INSTANCE NAME)'.  if you need to copy the database from the instance to the default, do that via backup from the instance and restore to the default database. then just uninstall the instance sql server from control panel > add/remove programs. 

i also wasn't able to log in with "Server=localhost". i had to use "Server=(local)". 

 


Sunday, 10 October 2004 11:24:36 (GMT Daylight Time, UTC+01:00)  #    Comments [0]  Database

# Sunday, 03 October 2004
Complications with textbox and Newline and Carriage Return characters

My windows application uses a multi-line textbox to allow the user to update text, which gets sent to and from a web service, and then into and out of a sql database.  Somewhere along the way, the \r\n characters turn into \n characters.  So when i re-load the string from the web service into the textbox, it gets displayed as block characters instead of proper line breaks.  I wrote the following simple function to work around this issue. 

It firstly removes all the \r characters, which has the effect of changing the \r\n characters to \n. Then it replaces the \n chars to \r\n. 

Note: The reason you can't just replace the \n chars with \r\n is because you would end up with \r\r\n chars if there were \r\n's in the string before you did the replace.

/// 
/// this method formats a string for correct display in a multiline text box.
/// It removes \n characters and replaces them with correct \r\n chars
/// 
public static string FormatForMultiLineTextBox(string s)
{
return s.Replace("\r","").Replace("\n","\r\n");
}

i will also take this opportunity to share a method i use to prevent errors caused by sending certain binary characters across a web service (at least in WSE 2).  The method removes all un-useful binary characters (useful... in terms of my app).

/// 
/// This method removes all binary characters except:
/// Vertical Tab 0x09
/// New Line 0x0A
/// Carraiage Return 0x0D
/// 
public static string StripBinaryChars(string s)
{
    return Regex.Replace(s, @"[\x00-\x08\x0B-\x0C\x0E-\x1F]","");
}

see www.asciitable.com for more information on the hex codes for these binary characters.


Sunday, 03 October 2004 18:40:37 (GMT Daylight Time, UTC+01:00)  #    Comments [0]  .Net Windows Forms

# Sunday, 19 September 2004
Problems using Visual Studio.Net and Visual Source Safe with Web Projects

If you get annoyed at Visual Source Safe's complications with using asp.net web projects, and integrating them with Visual Studio.Net, an increasingly popular approach is to use 'class library' projects instead of web projects.  (Of course, this problem will disappear with Whidbey but i'm still using VS 2003).  A web project compiles a dll / class library anyway, and VS doesn't have to interact with IIS to load the project.  It isn't hard to set up but it does require careful instructions to be followed.  A guy called Fritz Onion prepared the content below:

This is copied/pasted here in case Fritz's link changes or disappears. The original content is available from:
http://www.pluralsight.com/fritz/Samples/aspdotnet_without_web_projects.htm

Reference prepared by Fritz Onion

The Web Project wizard in Visual Studio .NET is convenient for creating quick ASP.NET applications on your local machine, but in an effort to simplify your life, it also makes many decisions for you that are difficult to change if you need more flexibility. My biggest pet peeve with Web Projects is that you cannot even open a .sln file if the virtual directory mapping in IIS is not set up correctly. I also dislike the way it places .sln and .csproj | .vbproj files in a separate location from the actual source files (I understand that this is necessary to allow application creation directly on a server, but I never deploy that way).

As a result, most of my web projects are created as standard class library projects. Unfortunately this means that you don't get the nice Web component wizards (like WebForms and UserControls). However, with a little tweaking, you can have it all.  I have prepared this document describing how to enable these wizards in class library projects (thanks to Dan Sullivan for pointing out how to do this), as well as how to convert existing Web Projects to class library projects and still keep the nice integrated debugging.

To enable Web wizards in a class library project:

In a directory called

C:\Program Files\Microsoft Visual Studio .NET 2003\VC#\CSharpProjectItems\LocalProjectItems

is a file callled localprojectitems.vsdir.

Likewise in a directory

C:\Program Files\Microsoft Visual Studio .NET 2003\VC#\CSharpProjectItems\WebProjectItems

is a file called webprojectitems.vsdir.

If open the second file with notepad you can figure out the lines to copy to the first file to be able to add the usual files you need to create an aspx page or web service to a class lib project.

Once you have copied these thing open VS, open a class lib and go to add new item and you will see these additional file types available.

To set the output of a class library project to go to a /bin directory of your choosing:

1. Right-click on the project and select properties
2. Set Configuration to 'All Configurations' to affect both debug and release builds
3. Under configuration properties/build set the OutputPath to the /bin directory
 

To convert an existing web project into a class library project:

1. Open the .sln file in a text editor, and change the reference to the project from an http://... reference to a simple reference to the .csproj (or .vbproj) filename. For example:
change:
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApplication133", "http://localhost/WebApplication133/WebApplication133.csproj", "{39CB37A5-F735-4684-B5DA-DD355B683090}"

to:
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WebApplication133", "WebApplication133.csproj", "{39CB37A5-F735-4684-B5DA-DD355B683090}"

2. If there is one, delete the .webinfo file
3. Open the .csproj (or .vbproj) file and change the ProjectType attribute from "Web" to "Local"

To set up a class library project to run a browser when you debug it:

1. Right-click on the project in the solution explorer and select properties
2. Under Configuration Properties/Debugging, change Debug Mode from 'Project' to 'URL'
3. Hit Apply
4. In the Start URL field, enter the complete url to the page you want to hit to debug, like:
http://localhost/testproj/webform1.aspx


Sunday, 19 September 2004 23:32:44 (GMT Daylight Time, UTC+01:00)  #    Comments [0]  .Net General

# Tuesday, 14 September 2004
A sample NTbackup script, with the current date/time in the filename and backup label

This script is based on the FAQ on http://www.jsiinc.com/SUBE/tip2200/rh2265.htm.

If you ever tried to automate NTbackup, you probably got it up and running, scheduled every day or week, but then noticed over time that the date and time labels that go on the backup file are the current date/time of when you created the backup set.  This useful shell script provides a more intelligent solution by parsing the current date and time and inserting them into the filename and backup label.  This makes the backups much easier to identify in the case where you need to restore some files.

The script below makes a full backup (not differential) of the files specified in the backup set.bks. It doesn't verify the backup, and lastly it sends a copy of the backup file to another computer (just in case), that's what the last 3 lines are for.  You can obviously remove this step if you don't want it.

If you don't fully understand all the parameters of the NTbackup.exe... command, it's explained well here.

Save the following text as a .cmd file and add it is a scheduled task in Windows.

@for /f "Tokens=1-4 Delims=/ " %%i in ('date /t') do  @set dt=%%i-%%j-%%k-%%l
@for /f "Tokens=1" %%i in ('time /t') do @set tm=-%%i
@set tm=%tm::=-%
@set dtt=%dt%%tm%
@echo Copying backup set: %dtt%.
@echo Please wait...
@C:\WINDOWS\system32\ntbackup.exe backup "C:\Documents and Settings\Administrator\Local Settings\Application Data\Microsoft\Windows NT\NTBackup\data\backup set.bks" /a /d "Backup %dtt%" /v:no /r:no /rs:no /hc:off /m normal /j "%dtt%" /l:s /f "G:\Auto Backups\Backup %dtt%.bkf"

@echo Sending backup file to Server2. Please wait...
@xcopy "@G:\Auto Backups\Backup %dtt%.bkf" "@\\Server2\Backup_Copy" /Y
@echo Finished.

Tuesday, 14 September 2004 11:18:09 (GMT Daylight Time, UTC+01:00)  #    Comments [17]  Windows Server

# Friday, 10 September 2004
How to turn off Windows auto-expand (and search) for compressed folders

I have a lot of .zip files floating around my computer and Windows XP/2003 includes them with regular folders when browsing in Explorer.  Also, when you search for files, Windows searches inside .zip files which can take a long time because they need to be uncompressed every time to be searched. 

I personally don't want this feature, and after a bit of looking around, i came across a simple solution.  Just unregister the component that does the searching within compressed folders.  Note: this doesn't stop you opening compressed folders, it just means they don't get included in the Windows Explorer tree-view, and they don't get included in searching with the Indexing Service.

Run the following command (Start > Run) or you can put it in the Run section of the Windows Registry in case Windows automatically adds back the zip dll.

regsvr32 /u C:\windows\system32\zipfldr.dll 

If you go need to put it back again, then run:

regsvr32 C:\windows\system32\zipfldr.dll 

Many thanks to 'SJB' for his/her post on http://www.annoyances.org/exec/forum/winxp/1054284272


Friday, 10 September 2004 22:36:46 (GMT Daylight Time, UTC+01:00)  #    Comments [0]  Windows Server

# Thursday, 29 July 2004
Controlling a dial-up connection via a web service

Background

I just finished writing a simple client/server .Net application that allows windows PCs on a LAN to control the dial-up connection on a web server. 
I'm currently using it at home on a small ad-hoc wireless network because the windows Internet Connection Sharing setting for 'dial on-demand' is very unreliable and it dials up when you don't want it to.  This way you control when it connects and disconnects. Also, i was using terminal services to connect and disconnect which is way overkill!

I have put the source code and executables online for anyone to download, use modify etc. Download: RemoteDialer.zip (94 k).  There is a readme file in there, but here are the instructions anyway which explain how it works and how to set it up.

How it works

The web server has methods for Dial() and Hangup().  They each call a batch file with Process.Start, which is configured to output the result of the operation to a text file.  The batch files use the rasdial.exe tool to connect and disconnect the connection. The web service reads the text file before sending back the contents of it, to the client that requested the operation.

The desktop application for client PCs has a system tray icon, with a right-click menu to Start or Stop the connection.

There is also a web page to connect/disconnect, so you can allow non-windows users (who obviously couldn't run the desktop app) who are on your network to control the connection. To go to this page, just go to the address of the v.dir on the server.

Setup

To configure the web server:

 - set up a new application pool which runs as Local Service
 - copy the 'Web' folder to the web server
 - make it a virtual directory
 - set the AppPool for the v.dir to the appPool you just created
 - Copy the 2 batch files in the 'Batch Files' folder to the server.
 - It's easiest to put them in the c:\ root, otherwise you can
   update the web.config application keys accordingly.

To configure the windows PCs:

 - Locate the RemoteDialer.exe.config file in \WinClient\bin
 - Adjust the http value key to match the server and v.dir name on the
   server.
 - Copy the WinClient\Bin folder to each PC
 - Run the .exe and you will see a new icon the system tray.
 - Right-click the tray icon to start or stop the dial up connection
 - The status of the operation is outputted to a pop up box.

Note: The reason for the new Application Pool is so that the web service
can interact with the system and write the output of operations
to text files.

 

If you have any comments or queries on it, or if there are bugs or problems, email me.  tim@mackeyNO_SPAM_PLEASE.ie


Thursday, 29 July 2004 11:29:17 (GMT Daylight Time, UTC+01:00)  #    Comments [4]  .Net General

# Monday, 26 July 2004
A great ASP.NET treeview control that is compatible with other browsers

I'm building a web front-end for my content management system (so that i can sell it to clients who don't run 100% windows PCs).  and i needed a cross-platform treeview control.  i did a quick search and noticed that the CrapStuff Treeview listed on asp.net was a popular one (http://crapstuff.craponne.org).  Ignoring the unusual name i tried it out and am delighted with it.  i have used the microsoft.ui.webcontrols treeview before and found it frustrating on several issues, that others have also encountered and have remained unresolved due to MS not supporting the control.

programatically the CrapStuff Treeview is great to work with, and i like the DHTML support also so that the control can be expanded fully without any postbacks, unless you want them to happen.

the author's name is Pascal Craponne so that's where he gets the name i suppose.  it's a great control and he has given it out for free.  thank you Pascal!


Monday, 26 July 2004 23:05:05 (GMT Daylight Time, UTC+01:00)  #    Comments [1]  Asp.Net