in

ASP.NET Weblogs

Georged Weblog

Have you georged your mind?
  • Now it WON'T run differently under debugger

    Scott Hanselman has blogged recently about our experience with nasty tricks Visual Studio debugger can play on you. Turns out, it's possible to run and debug normally without resorting to a secondary thread spin-off. But there is a price to pay: remote debugging for web services must be disabled. Add this to your app.config:
     
    <configuration>
       <system.diagnostics>
          <switches>
             <add name="Remote.Disable" value="1" />
          </switches>
        </system.diagnostics>
    </configuration>
     
    Sweet.
    Posted Mar 17 2005, 11:43 AM by georged with 3 comment(s)
    Filed under:
  • NT Backup reloaded

    I already mused about NT Backup before. Since then things started to go a bit sideways in terms of reliability of disk backups immediately followed by Exchange 2003 backup. For some reason media manager refused to recognise that disk backup has finished and Exchange dump was consistently failing. Poking around yielded the following update to the batch (set names are now really nice :-).


    @echo off

    Rem get date into a vairable so we can create good media name
    rem for /F "usebackq delims=" %%i IN (`date /t`) DO set dt="%%ibackup media"
      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 ---------------------------------------- > report.txt
    @echo Backup job started %dtt% >> report.txt
    @echo ---------------------------------------- >> report.txt

    Rem Set folder name containing backup log files
    set fld=C:\Documents and Settings\Administrator\Local Settings\Application Data\Microsoft\Windows NT\NTBackup\data\

    @echo net stop "Removable Storage" >> report.txt
    net stop "Removable Storage" >> report.txt
    @echo ---------------------------------------- >> report.txt

    rem refresh media (is that why backup is failing?!)
    @echo rsm.exe refresh /LF"HP C1537A SCSI Sequential Device" >> report.txt
    start /wait rsm.exe refresh /LF"HP C1537A SCSI Sequential Device" >> report.txt
    @echo ---------------------------------------- >> report.txt

    sleep 30

    Rem Perform Files backup
    @echo C:\WINNT\system32\ntbackup.exe backup "@C:\admin\files.bks" /N "%dtt%" /D "File daily %dtt%" /v:yes /r:no /rs:no /hc:on /m normal /J "File daily %dtt%" /l:s /P "4mm DDS" /UM >> report.txt

    @echo ---------------------------------------- >> report.txt

    C:\WINNT\system32\ntbackup.exe backup "@C:\admin\files.bks" /N "%dtt%" /D "File daily %dtt%" /v:yes /r:no /rs:no /hc:on /m normal /J "File daily %dtt%" /l:s /P "4mm DDS" /UM

    Rem This dir command will list all log files sorted by date in bare format
    set fcmd=dir "%fld%*.log" /OD /A-D /B

    Rem set command will set lastf variable to the last file in set, i.e. the latest one
    for /F "tokens=* delims= " %%i in ('%fcmd%') do set lastf=%fld%%%i

    type "%lastf%" >> report.txt

    sleep 120

    rem refresh media (is that why backup is failing?!)
    @echo rsm.exe refresh /LF"HP C1537A SCSI Sequential Device" >> report.txt
    start /wait rsm.exe refresh /LF"HP C1537A SCSI Sequential Device" >> report.txt
    @echo ---------------------------------------- >> report.txt

    sleep 120

    Rem Perform Exchange backup
    @echo ---------------------------------------- >> report.txt
    @echo C:\WINNT\system32\ntbackup.exe backup "@C:\admin\exchange.bks" /A /T %dtt% /D "Exchange Daily %dtt%" /V:yes /R:yes /RS:no /HC:on /M normal /J "Exchange Daily %dtt%" /L:s >> report.txt
    @echo ---------------------------------------- >> report.txt

    C:\WINNT\system32\ntbackup.exe backup "@C:\admin\exchange.bks" /A /T %dtt% /D "Exchange Daily %dtt%" /V:yes /R:yes /RS:no /HC:on /M normal /J "Exchange Daily %dtt%" /L:s

    Rem This dir command will list all log files sorted by date in bare format
    set fcmd=dir "%fld%*.log" /OD /A-D /B

    Rem set command will set lastf variable to the last file in set, i.e. the latest one
    for /F "tokens=* delims= " %%i in ('%fcmd%') do set lastf=%fld%%%i

    type "%lastf%" >> report.txt

    sleep 120

    rem eject media
    @echo ---------------------------------------- >> report.txt
    @echo rsm.exe eject /PF"%dtt% - 1" /astart >> report.txt
    @echo ---------------------------------------- >> report.txt
    start /wait rsm.exe eject /PF"%dtt% - 1" /astart >> report.txt

    sleep 30

    c:\admin\blat report.txt -t youraddress@yourdomain.com -s "Backup Report" -mime -server yoursmtpserver -f "backup@yourdomain.com" -q

    Rem Cleanup
    set fld=
    set fcmd=
    set lastf=
    set dt=
    set tm=
    set dtt=


     

    Posted Jul 28 2004, 11:20 PM by georged with 2 comment(s)
    Filed under:
  • And execution continues

    Nothing makes our life more interesting than ASP.NET behaviour at debugger termination. This is a short version of three lost hours:

    Create an empty page and add the following code

    private void Page_Load(object sender, System.EventArgs e)
    {
      
    const string CONNECT_STRING = "server=(local);uid=sa;pwd=password;database=msdb;persist security info=True";
       SqlConnection con =
    new SqlConnection(CONNECT_STRING);
       con.Open();
       SqlTransaction tran = con.BeginTransaction();
       try
       {
         
    new SqlCommand("create table temptable(id int)", con, tran).ExecuteNonQuery();
          tran.Commit();
      
    }
      
    catch
      
    {
          tran.Rollback();
         
    throw;
       }
      
    finally
       {
          con.Close();
       }
    }

    Add breakpoint at “new SqlCommand“ line and hit F5

    When debugger stopped at breakpoint hit Shift-F5.

    And here is trace from SQL Profiler:

    SET TRANSACTION ISOLATION LEVEL READ COMMITTED;BEGIN TRANSACTION
    go
    create table temptable(id int)
    go
    COMMIT TRANSACTION
    go

    Seems that ASP.NET is entitled to do whatever it wants at debugger termination including successful execution of the entire program.

    NOT sweet.

     

    Posted Mar 09 2004, 09:57 PM by georged with 6 comment(s)
    Filed under:
  • Books upgrade

    I was looking at Programming ASP.NET, Second Edition on Amazon and suddenly the question came up:

    Why do we always expect software vendors to offer upgrades for their products but no one expects that for books? Is there some economical rationale I'm missing? How cool would it be to walk into a bookstore holding the first edition and to hear "Oh, yes, sir, this mighty book you've got in your hands qualifies you for an upgrade discount of 40%".

    Posted Nov 30 2003, 01:55 AM by georged with 2 comment(s)
    Filed under:
  • XmlPleaseIgnore

    There is a handy class UriBuilder which, unlike Uri, allows full read-write access to all the components of Uri. However, problems started when I tried to serialise it using XmlSerializer. The following code:

    using System;
    using System.Collections;
    using System.Xml;
    using System.Xml.Serialization;
    public class XmlPleaseIgnore
    {
        public static void Main()
        {
            UriBuilder b = new UriBuilder("http", "localhost", 80, "/test/default.aspx");
            XmlSerializer x = new XmlSerializer(b.GetType());
            x.Serialize(Console.Out, b);
        }
    }

    quickly produced this:

    Unhandled Exception: System.InvalidOperationException: There was an error reflecting type 'System.UriBuilder'. ---> System.InvalidOperationException: System.Uri cannot be serialized because it does not have a default public constructor.

    A bit of digging revealed that UriBuilder.Serialize method

    ...converts the public fields and read/write properties of an object into XML. It does not convert methods, indexers, private fields, or read-only properties. To serialize all of an object's fields and properties, both public and private, use the BinaryFormatter.

    And, of course, Uri property of UriBuilder is read-only property and, to make the matter worse, it does not have public default constructor. If it were my class I would apply XmlIgnore attribute to the member and that would do the trick. As I found, with a bit of code it can be done for external classes as well:

    using System;
    using System.Collections;
    using System.Xml;
    using System.Xml.Serialization;
    public class XmlPleaseIgnore
    {
        public static void Main()
        {
            // add XmlIgnore attribute and attach it to Uri member of UriBuilder class
            XmlAttributes attrs = new XmlAttributes();
            attrs.XmlIgnore = true;
            XmlAttributeOverrides over = new XmlAttributeOverrides();
            over.Add( typeof(UriBuilder), "Uri", attrs);
            
            UriBuilder b = new UriBuilder("http", "localhost", 80, "/test/default.aspx");
            XmlSerializer x = new XmlSerializer(b.GetType(), over); // override attributes
            x.Serialize(Console.Out, b);
        }
    }
    And here is the output:
    xml version="1.0" encoding="utf-8" ?>
    <UriBuilder
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Fragment />
    <Host>localhostHost>
    <Password />
    <Path>/test/default.aspxPath>
    <Port>80Port>
    <Query />
    <Scheme>httpScheme>
    <UserName />
    > 

    Note that attribute is applied to a member of a class and therefore I can also serialise my own classes which have UriBuilder as a member variable.

    Sweet.

    Posted Nov 06 2003, 12:05 PM by georged with 3 comment(s)
    Filed under:
  • "Static" variables in SQL

    I did not realise that declared variables in SQL are effectively “static” when used in rowsets. That is, the following code:

    create table roles(role nvarchar(50))
    GO
    insert roles
    select 'Administrator' union
    select 'Editor' union
    select 'User'
    go

    declare @roles nvarchar(1024)
    select @roles = isnull(@roles + ', ', '') + role from roles
    select @roles
    go

    drop table roles
    go

    yeilds “Administrator, Editor, User“.

    Wow! Now instead of returning rowset of roles for a user and then concatenating results in client-side code, I can just write a function similar to:

    create function fnGetUserRoleVerbose(@userid int, @delim nvarchar(2) = ', ')
    returns nvarchar(1024)
    as
    begin
       declare @role nvarchar(1024)
      
       select
          @role = isnull(@role + @delim, '') + roles.name 
       from
          users
          inner join users_roles
             on users.id = userid
          inner join roles
             on roleid = roles.id
       where
          users.id = @userid
     
       return @role
    end

    and then just do this:

    string roles = (string) SqlHelper.ExecuteScalar(
        myConnectionString, 
        CommandType.Text,
        string.Format("select dbo.fnGetUserRoleVerbose({0}, default)", userId));

     

    Posted Oct 16 2003, 11:29 PM by georged with 5 comment(s)
    Filed under:
  • Googless?

    Could not google this morning... Dig deeper...

    C:\>nslookup www.google.com ns1.google.com
    Server:  ns1.google.com
    Address:  216.239.32.10

    *** ns1.google.com can't find www.google.com: Non-existent domain

    I... can... work... without... Google... Must... continue... Try local brew...

    C:\>nslookup www.google.com.au ns1.google.com
    Server:  ns1.google.com
    Address:  216.239.32.10

    Non-authoritative answer:
    Name:    www.google.akadns.net
    Address:  216.239.53.99
    Aliases:  www.google.com.au

    Phew! Must be Anti-Oz conspiracy!

    Posted Oct 14 2003, 05:06 PM by georged with 3 comment(s)
    Filed under:
  • Be positive

    Was driving to the customer site in a really bad mood but one of the billboards made me laugh all the way: MBF - Australian health fund/private health insurer has a new motto: "BE POSITIVE". Way to go, PR boneheads! That's exactly what I don't want to be when it comes to my health :-)

  • Make it three days from now

    Did you know that in date fields in Outlook (Task, Appointment forms) you can type things like "tomorrow", "yesterday", "week from now", "in 2 days", "two weeks ago", "next year". Even "Christmas", "Boxing Day", "New Years Day", "Halloween",  "Cinco de Mayo" and "Independence day" work (though "Queens Birthday" and "tonight" do not :-)

    Very handy when your client says "lets talk again in three days" - saves you figuring out what date it's going to be in case you've been on a coding roll for 20 hours straight and lost track of time. Sweet.

  • $25 ASP.NET challenge

    I'm yet to see ASP.NET code which does not use '~' mapping feature in Server.MapPath. We all love this feature, except... wait a minute... it is not documented?! Search on MSDN failed to uncover any statement stating that '~' in MapPath function refers to a virtual root (the task was not made any easier by the fact that tilde is ignored in a search). Could it be that we're all typing megalines of code against undocumented feature? And what, apart from bazillions of angered developers around the world, will stop ASP.NET team from changing it in 2.0 from '~' to, say '$', 'œ', '¥' or '½', for this matter :-). 

    Now, here is the georged challenge: the first person who points me to a piece of documentation explaining usage of a tilde character in MapPath is entitled to AUS $25 (about US$17 and rising). Money will be transferred to a PayPal account or similar.

    Rules:

    1. It must be official documentation, i.e. references to samples, user groups, magazine articles, blogs, etc will not be considered.
    2. 'First' will be judged by UTC time of the reply/post/email.
    3. I decide who's first and whether pointer/answer is correct.
    4. if(you.disagree) goto 3;
    5. Ah, what the heck, Microsoft employees are also eligible to enter :-)
    Anyone?
     
    Cheers
    Georged
More Posts Next page »