CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeffrey Palermo [MVP]

Software management consultant and CTO, Headspring Systems

September 2005 - Posts

  • Why are error return codes evil? - level 100

    Miller ran across some code today that used error codes for return values.  We exchanged some bad examples of misusing error codes (or just using them, period).

    In languages without structured exception handling, we often used some sort of indicator to communicate when an error happened.  For instance, a DOS program (or batch file) has a return code retrievable using the ERRORLEVEL global variable.

    With my platform of choice (.NET) supporting structured exception handling, using return codes for error reporting is quite far on the evil spectrum.  Consider this code:

       1:  public int DoSomething(){
       2:      //omitted implementation
       3:      return -1;
       4:  }

    This method should be void.  It is using an integer to tell whether an error occurred or not.  If something went wrong, throw an exception:
       1:  public void DoSomething(){ 
       2:      throw new SomethingException();
       3:  }
     

    Then there is no chance of the program continuing while being broken under the covers.  Some folks call this method "failing fast".  If the program encounters a serios error that it can't handle, fail fast because a program not operating according to plan can only cause harm.  That's why so many people hate "On Error Resume Next" in VB.  Errors are simply ignored.  Some folks rigged up error handling in VB by using:

       1:  On Error Goto ErrHandler
       2:      'some code
       3:   
       4:  ErrHandler:
       5:      'do some error reporting

    The team had to be very disciplined to make this work.  One funny thing I came across was a statement like the following:

       1:  On Error Goto Hell
       2:      'some code
       3:   
       4:  Hell:
       5:      'do some error reporting

    Bottom Line:  Throw exceptions if something goes wrong.  Don't set a "magic number" and expect to remember to check that later on.
  • Is your connection string really secure? - level 200

    Jeremy highlights some foobar code that exposed a connection string to a database via a public static property on a class.  In the comments, there was some discussion about what to do with the connection string.  I'd like to address some common thoughts on connection strings (mostly concerning keeping the connection string secure).

    1. Secure the connection string:
      What exactly does that mean?  Secure from whom?  Hackers?  Developers? Random company employees who don't have access to the server anyway?  The connection string has the information needed to log on to a database as a particular user (ignoring integrated authentication for now).  The question each organization has to answer is "who do I want to keep this information from"?  If the answer is the general population of company employees and outsiders, then you don't have to do much of anything.  If you store it in plain text in a configuration file on the server, only those with access to the server can see that information.  This assumes that security on the server is set up correctly on the server.  If you want to keep it from server administrators, then I'd ask why you have server administrators working for you if you distrust them that much.
    2. Select the simplest deployment scenario that will secure your connection string from the people you don't trust
      • General population - anything will work because they don't have access to the server
      • Server Administrators - you have a management problem, and the admins you don't trust need to be fired. 
    3. Next plan for "IF" the server is compromised.
      • Use an account in the connection string that only has read privileges.  Grant execute explicitly for stored procedures that do updates.
      • Don't use the "sa" account.
      • Use network restrictions to only allow communication to the database server from the application server (yes, put your network admins to work).  This is really simple, actually.  The network simply won't route packets to the database server unless they come from the application server. 

    The above are my preferences.  The above tends to simplify deployments because there are few hoops to jump through because the connection string often resides with other application configuration.  I'll also address the sometimes popular thought to store the connection string in the registry and even encrypt it!

    • I think storing the connection string in the registry is pointless.  Why?  Because it doesn't gain you anything.  It only makes deployment more difficult.
    • Encrypting the connection string is making deployments even more difficult and just try to cope with a broken IT department.  Often the justification is to protect _when_ the machine is compromised.  First, if someone gains ADMINISTRATIVE access to the machine (in order to read the encrypted value from the registry), they own the machine.  This is really bad, and if they care about your database, they can just get the private key from the application (that is on that machine) and decrypt it anyway.  (even with DPAPI).

    My preference?  Store it in plain text in the configuration file for most applications.  If configuration files float around, and there is risk within the company (you have co-workers who should be fired), 1.  stop the configuration from floating around, and 2.  perhaps encrypt the connection string inside the configuration file (but realize that anyone with access to the private key can still get it).  If you are really concerned, run your application with a service account and use integrated authentication.  This poses another problem.  How are you securing the password to the service account?  And the cycle repeats itself.

    Bottom line:  Security is not an absolute.  It's not a switch that's turned on by using a published "best practice".  It's a number of steps that are determined by the established risks.  Evaluate the real risks with your particular application and make objective decisions based on _real_ needs.  Some "security steps" like storing the connection string in the registry often don't deliver value but instead hurt deployment ease and make application support more difficult.  Don't fall prey to Mordac, the Refuser, working in your I/T department,  who may insist on some inane "security measures".  Be practical.

  • Robert Scoble et al. on blogging - level 100

    I just finished listening to an MSDN webcast on "Blogging from the Developer's Perspective".  I used my technique for converting the webcast and listening on my MP3 player while I drove home and shopped for groceries. 

    In this webcast, Jeff Julian, John Alexander, and Robert Scoble spoke about blogging.  It was quite interesting especially when Robert's wife (the webcast moderator) contributed the advice not to read blogs while sitting at the dinner table. 

    Great webcast.  I recommend everyone listen.

  • Visual Studio 2005 Release Candidate thoughts for web projects part 1 - level 100

    I've now installed Visual Studio 2005 Release Candidate on a virtual pc with Windows 2003 Server SP1.  My primary focus at this point is the web projects.  I love ASP.NET, and I think it is a brilliant runtime.  I have a website management framework built on ASP.NET, and I commend the folks at Microsoft for this great framework.  I've kept up with ASP.NET 2.0 since Beta 1 came out, and Whidbey Beta 1 was stable enough to work alongside VS.NET 2003 on my dev machine for a long time. 

    There are a number of items I was displeased with during the Beta cycle.  One issue was excluding files from a web projects.  In Beta 2 it wasn't possible.  With the RC, it is possible, but the IDE appends ".exclude" to the end of the file name.  If you exclude BrokenClass.cs, it becomes "BrokenClass.cs.exclude".  This works as far as Visual Studio is concerned, but this will cause headaches in a real development environment.  For instance, source control systems don't support renaming that well.  Those that do require a manual step to associate the history of a file with the new renamed file.  The IDE just renames the file and goes on.  It's a partial solution, but it's a shame that this has to be so hard. 

    Using this "feature" isn't going to be feasible in real-world situations.  A developer would "exclude" a file from the project when he wants to ignore it.  It's not an acceptable scenario to allow the automatic renaming of files that just happen to be in that directory tree.  What's worse, you can't exclude a folder. . . only the files inside (which now requires a renaming of them). 

    Excluding files from a read web project is not supported in Visual Studio 2005.  We'll have to live with a workaround.  This thing that they _call_ "exclude from project" isn't usable, so it can't be called a feature.  It will only work in the most trivial of web projects that are isolated from the real world:  MSDN Events demos.

    I still don't understand what is SO special about web projects that they don't deserve a project file like the rest of the project types.  Scott Guthrie makes some statements here if you care to read about some other points.  Overall, the Microsoft team has done much more good than harm, and I commend them for that, and I'm also glad that they are open to accepting feedback.

  • National Weather Service provides RSS feeds for hurricanes - level 100

    The National Weather Service provides RSS feeds for all the significant weather activity.  Since I have family in Houston, I've subscribed to the RSS feed for Hurricane Rita.  It's amazing how RSS feeds have penetrated into so many different parts of the Internet.  Is RSS the next killer app?  It certainly is changing the way I work.
  • How to use FitNesse querystring "switches" - level 300

    You might have notice in the FitNesse urls, a "?test" at the end when you run a test page.  Also, when you edit a page, you are using "?edit".  There are many of these querystring switches you can use to do some interesting things.  You can see all of these by opening up the Java source:

      addResponder("edit", EditResponder.class);
      addResponder("saveData", SaveResponder.class);
      addResponder("tableWizard", TableWizardResponder.class);
      addResponder("search", SearchResponder.class);
      addResponder("searchForm", SearchFormResponder.class);
      addResponder("test", TestResponder.class);
      addResponder("suite", SuiteResponder.class);
      addResponder("proxy", SerializedPageResponder.class);
      addResponder("versions", VersionSelectionResponder.class);
      addResponder("viewVersion", VersionResponder.class);
      addResponder("rollback", RollbackResponder.class);
      addResponder("names", NameWikiPageResponder.class);
      addResponder("properties", PropertiesResponder.class);
      addResponder("saveProperties", SavePropertiesResponder.class);
      addResponder("whereUsed", WhereUsedResponder.class);
      addResponder("refactor", RefactorPageResponder.class);
      addResponder("deletePage",DeletePageResponder.class);
      addResponder("renamePage", RenamePageResponder.class);
      addResponder("movePage", MovePageResponder.class);
      addResponder("pageData", PageDataWikiPageResponder.class);
      addResponder("createDir", CreateDirectoryResponder.class);
      addResponder("upload", UploadResponder.class);
      addResponder("socketCatcher", SocketCatchingResponder.class);
      addResponder("fitClient", FitClientResponder.class);
      addResponder("deleteFile", DeleteFileResponder.class);
      addResponder("renameFile", RenameFileResponder.class);
      addResponder("deleteConfirmation",DeleteConfirmationResponder.class);
      addResponder("renameConfirmation",RenameFileConfirmationResponder.class);
      addResponder("raw", RawContentResponder.class);
      addResponder("rss", RssResponder.class);
      addResponder("import", WikiImportingResponder.class);
      addResponder("files", FileResponder.class);
      addResponder("shutdown", ShutdownResponder.class);
      addResponder("format", TestResultFormattingResponder.class);
      addResponder("symlink", SymbolicLinkResponder.class);

    Some of the more interesting ones I like are rss, fitClient, and raw.  Yes, "shutdown" will actually shut down the wiki.  Use with care.

    The "rss"  querystring parameter will give you an rss feed, and the "raw" parameter will spit out the exact contents of the underlying "content.txt" file.  This is the exact wiki text that the user entered.  "fitClient" is the one that interests me most because it will spit out the html tables needed to actually run the FitNesse tests offline or in a debugger.  The html is rendered to the browser, but there is a bug in the FitClientResponder class that violates a rule of an Http request, so I can't programmatically get this page with .Net code (say, the WebClient class). 

    Something very interesting I've done with the "raw" switch is to pull it back into an NUnit helper class, run it through some simple translator code:

                      StringReader reader = new StringReader(wikiText);

                      string line = reader.ReadLine();

                      while(line != null)

                      {

                            line = line.Trim();

                            if(line.StartsWith("!"))

                            {

                                  string row = line.Trim('!', '|');

                                  this.StartTable(row);

                            }

                            else if(line.StartsWith("|"))

                            {

                                  // get rid of leading and trailing "|", and split on the rest.

                                  string[] columns = line.TrimStart('|').TrimEnd('|').Split('|');

                                  this.AddRow(columns);

                            }

                            line = reader.ReadLine();

                      }

                      reader.Close();

     

    Then, I have the html tables that allow me to create a new Parse object by passing in this html string.  Then it's trivial to execute this against the FitNesse test engine.

    By the way, Google Desktop 2 is great.  I've been using it to search and find source code.  Even if the documentation is complete, or you want to dig more, Desktop search is great for finding tidbits in the source code itself (I've used MSN search as well.  They both work well).

  • How to mock a static member for test-driven development - level 400

    If you are interested in mocking a static member or class in order to facilitate testing a component in isolation, you are traveling down the wrong path.  First, to be blunt, you cannot mock a static.  Static members belong to the AppDomain, and are not replaceable instances.  For instance, if I have a class with static methods called SqlHelper (like version 2 of the DAAB), and I want to unit test a class that calls methods on SqlHelper, I'm stuck.  I can't do it.  SqlHelper's static methods call directly into data access code, so now anything that calls SqlHelper has a transitive dependency on the data access code (and most likely the database behind it). 

    So you have code that can't be tested in isolation.  What do you do? 

    • Don't waste you time trying to find a solution to mocking the static members of SqlHelper.  You can't do it.  Just like you can't run Java Swing code inside a WinForms .Net project - there's no point in searching for a solution because one doesn't exist). 
    • Refactor your code because your component is highly coupled.  You desire loosely coupled code.  Change your SqlHelper class's static members into instance members, or if you can't, wrap it in another class - let's call this SqlRunner.
    • Accept an instance of SqlRunner in the constructor of the component you are testing; save it in a class-level variable.
    • Unit test to your heart's content.

    It's really that simple.  In your test, you can create a dynamic mock of the SqlRunner class and pass that into the constructor of your tested component.  Your component will now call out to your mock, and you have succeeded in testing your component in isolation. 

    You may be wondering what to do if you need to call some static members in the .Net framework.  For instance, what about HttpContext.Current in a web control?  Current is a static property that returns the current instance of the HttpContext class.  You do not want to call that property directly in your code if you ever hope to test it.  In that case, use the same technique as above with a thin wrapper class that knows how to get HttpContext.Current.

    If you still aren't convinced about the rigidity of statics in code, feel free to keep searching, but when you come back around and follow the above steps, come back and leave a comment.

  • EZWeb 1.2 release 3 now available!! Go download!!!!

    EZWeb 1.2 release 3 is now available for download on GotDotNet.  I've enhanced slightly the included templates, and I enabled support for multiple independent websites inside the same hosted instance of EZWeb.  That means that a single hosting account can support an unlimited number of websites, and they will all appear independent from one another.

    If you are using one of the previous versions of EZWeb, you should upgrade to release 3.  As always, if you find EZWeb useful, blog about it or tell your friends, and please give me feedback.  EZWeb is ideal for any type of informational website such as User Group websites or family websites.  It supports file and image uploads as well.

    You can see the demo site at www.palermofamily.com

    At the very least, download it and try it out on your own box.  It's the simplest web app you'll ever use.  Follow the instructions in the ReadMe.

  • How to version FitNesse acceptance tests (yes, the wiki pages) - level 300

    Follow this post to easily version your FitNesse wiki acceptance tests (or any other tree of files).

    The product manager and his crew will use the FitNesse wiki to author and maintain acceptance tests for the system.  These tests are stored in files on the FitNesse server.  This presents a unique problem of backing up and versioning the tests.  The wiki itself supports 15 levels of modifications, but we use Subversion as the standard versioned backup at the company, so we'd like the acceptance tests to go there.

    Here is how we solved this problem:

    We created a new project in CruiseControl.Net to watch the wiki.  Call it WikiWatcher.  This project uses "filesystem" as it's source control to watch.  We point this at the FitNesse directory, and CC.Net will react when any of the files there change.  CC.Net then kicks of a Nant script, and that gives us all the power we need.  In Nant, we run two <exec/> task.  The first adds any files not currently in SVN, and the second commits the files.  NantContrib only provides update and checkout tasks for SVN, so we had to hit svn.exe directly with some command line arguments.  This system works well, and within 60 seconds of a Wiki modification, the changes are versioned and backed up in SVN.  (The CruiseControl.Net documentation can fill in any gaps you may have)

    Here is the CC.Net config section that defines our project:

    <!-- this project watches the fitnesse wiki and backs things up in subversion -->
      <project name="WikiWatcher">
        <webURL>http://<serverName>/ccnet/Controller.aspx?_action_ViewProjectReport=true&amp;server=aufile01&amp;project=FitNesseWatcher</webURL>

        <triggers>
          <intervalTrigger seconds="60" />
        </triggers>

        <modificationDelaySeconds>15</modificationDelaySeconds>
        <publishExceptions>false</publishExceptions>

        <labeller type="defaultlabeller">
          <incrementOnFailure>false</incrementOnFailure>
        </labeller>

        <sourcecontrol type="filesystem">
          <repositoryRoot>C:\fitnesse</repositoryRoot>
          <autoGetSource>false</autoGetSource>
          <ignoreMissingRoot>false</ignoreMissingRoot>
        </sourcecontrol>

        <tasks>
          <nant>
            <executable>c:\<some path>\trunk\bin\nant\NAnt.exe</executable>
            <baseDirectory>c:\<some path>\trunk</baseDirectory>
            <buildFile>WikiWatcher.build</buildFile>
            <targetList>
              <target>commit</target>
            </targetList>

            <buildTimeoutSeconds>1500</buildTimeoutSeconds>
          </nant>
        </tasks>

        <publishers>
          <xmllogger />
        </publishers>

      </project>

    This is pretty simple.  Just add the above as a CC.Net project node, and you're off to the races.  The Nant script is even simpler.
    Here's the Nant script:

    <?xml version="1.0" encoding="utf-8" ?>
    <project name="WikiWatcher" default="commit" xmlns="
    http://nant.sf.net/release/0.85-rc3/nant.xsd">
     <property name="baseWikiDir" value="C:\fitnesse"/>
     <target name="commit" description="Commits entire wiki directory to source control">
      <fileset basedir="${baseWikiDir}" id="wikiFiles">
       <include name="**"/>
      </fileset>
      <echo message="My build ran"></echo>
      <exec program="c:\program files\subversion\bin\svn.exe"
            commandline="add --force *.*"
            workingdir="${baseWikiDir}" />
      <exec program="c:\program files\subversion\bin\svn.exe"
            commandline="ci -m&quot;automatic checkin&quot; --username <some user> --password <some password>"
            workingdir="${baseWikiDir}" />
     </target>
    </project>

    This adds and commits all FitNesse files to SVN, and we're done.

  • How to download MSDN webcasts and listen on your MP3 player - level 100

    For a while, MSDN Live Meeting webcasts had to be captured manually by something like NetTransport 2.  Now, Microsoft is offering a .wmv file download for offline viewing.  Personally, I get more out of the audio, and I can listen on the way to/from work as well as while at the gym.  My wife laughs about how "nerdy" I am because I have headphones at the gym while working out, and while folks think I"m listening to some motivating heavy metal, I'm listening to new and cool ways to use the .Net Framework!

    I use Windows Media Encoder 9 to get pull out the audio stream and create a .wma file that can be listened to with any portable audio player.  I use 1.25% time compression to shorten the time it takes to listen to the content.   It makes the speaker talk faster, but it's still good.  It can take out long pauses as well.

  • How to integrate FitNesse acceptance tests into your CC.Net build - level 300

    I'm doing a lot with FitNesse lately, and it's going quite well.  Unit testing ensures that each component is doing what it is supposed to, and integration testing ensures that the components work well together.  Acceptance tests are a bit different.  They actually test that the software does what the customers think it's doing.  They test that the developer understood the business need.  They give the customer (or product manager) assurance that the system actually works.

    With FitNesse, our product manager (and crew) can  use a simple wiki to exercise the system.  The developers create test Fixtures that speak in the domain language but actually exercise the system under test.  A user may type:

    !|fit.ActionFixture|
    |start|Emailer|
    |press|SendDefaultEmail|
    |check|NumEmailsSent|

    This simple table is enough to actually exercise the system under test and get it to do something.  If all is well, the Emailer will send a default email.  If this test fails, it saves the company from a black eye when a user encounters the problem.

    It was a little tricky to get the FitNesse test integrated with our CC.Net build.  We wanted the acceptance test to be a current status report of where we are.  When all the acceptance tests are passing, we are done.  Consequently, we didn't want failing acceptance tests to break the build.  Only NUnit tests break the build because they should _always_ be passing.  No problem.  We create a new target with some exec tasks:

    <exec program="<path to TestRunner.exe>" commandline="-results <some directory>\FitNesse-Results.html <FitNesse server> <port> <TestSuite>" failonerror="false"/>

    This will actually call the FitNesse server (with the wiki on it) and execute all the acceptance tests.  This will produce a file in the raw FitNesse format.  We'd like it in xml so we can incorporate it in the CC.Net build report.  Xml transforming isn't a part of the .Net port, but it is in the Java version, so we'll just use it.

    <exec program="java.exe" commandline="-cp bin\fit\fitnesse.jar fitnesse.runner.FormattingOption <some directory>\FitNesse-Results.html xml <some directory>\Fit-Results.xml <FitNesse server> <port> <TestSuite>" failonerror="false"/>

    This hooks into the transform logic on the FitNesse server to change our raw output file to a nice Xml format.  Now we have something that CruiseControl.Net can use for a build report and email.  We will have to make an Xsl, though.  Here's a simple Xsl that will pull out the FitNesse summary information and through it out to your CC.Net build summary:

    <?xml version="1.0"?>

    <xsl:stylesheet

    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <xsl:output method="html"/>

    <xsl:variable name="fit.result.list" select="//testResults/result"/>

    <xsl:variable name="fit.wrongpagecount" select="countU$fit.result.list/counts/wrong[text() > 0])" />

    <xsl:variable name="fit.ignorespagecount" select="countU$fit.result.list/counts/ignores[text() > 0])" />

    <xsl:variable name="fit.exceptionspagecount" select="countU$fit.result.list/counts/exceptions[text() > 0])" />

    <xsl:variable name="fit.correctpagecount" select="countU$fit.result.list/counts[wrong/text() = 0 and exceptions/text() = 0 and ignores/text() = 0])" />

    <xsl:variable name="fit.correctcount" select="//testResults/finalCounts/right"/>

    <xsl:variable name="fit.failures" select="//testResults/finalCounts/wrong"/>

    <xsl:variable name="fit.notrun" select="//testResults/finalCounts/ignores"/>

    <xsl:variable name="fit.exceptions" select="//testResults/finalCounts/exceptions"/>

    <xsl:variable name="fit.case.list" select="$fit.result.list//test-case"/>

    <xsl:variable name="fit.suite.list" select="$fit.result.list//test-suite"/>

    <xsl:variable name="fit.failure.list" select="$fit.case.list//failure"/>

    <xsl:variable name="fit.notrun.list" select="$fit.case.list//reason"/>

    <xsl:variable name="colorClass">

    <xsl:choose>

    <xsl:when test="$fit.exceptionspagecount > 0">fiterror</xsl:when>

    <xsl:when test="$fit.ignorespagecount > 0">fitignore</xsl:when>

    <xsl:when test="$fit.wrongpagecount > 0" >fitfail</xsl:when>

    <xsl:otherwise>fitpass</xsl:otherwise>

    </xsl:choose>

    </xsl:variable>

    <xsl:variable name="fit.tests.present" select="countU//testResults/result) > 0 or count(/cruisecontrol/build/buildresults//testsuite) > 0" />

    <xsl:template match="/">

    <xsl:choose>

    <xsl:when test="$fit.tests.present">

    <style>

    *.fitpass{

    background-color: #AAFFAA;

    }

    *.fitfail{

    background-color: #FFAAAA;

    }

    *.fiterror

    {

    background-color: #FFFFAA;

    }

    *.fitignore

    {

    background-color: #CCCCCC;

    }

    *.fitheader{

    border: solid 1px black;

    margin: 1px;

    padding: 2px;

    }

    *.line{

    margin: 5px;

    }

    </style>

    <div>

    <div class="{$colorClass} fitheader">

    <strong>FitNesse Summary -- Test Pages:</strong> <xsl:value-of select="$fit.correctpagecount"/> right, <xsl:value-of select="$fit.wrongpagecount"/> wrong,

    <xsl:value-of select="$fit.ignorespagecount"/> ignored, <xsl:value-of select="$fit.exceptionspagecount"/> exceptions

    <strong>Assertions:</strong> <xsl:value-of select="$fit.correctcount"/> right, <xsl:value-of select="$fit.failures"/> wrong,

    <xsl:value-of select="$fit.notrun"/> ignored, <xsl:value-of select="$fit.exceptions"/> exceptions

    </div>

    <xsl:for-each select="$fit.result.list">

    <xsl:variable name="colorClass">

    <xsl:choose>

    <xsl:when test="counts/exceptions > 0">fiterror</xsl:when>

    <xsl:when test="counts/ignores > 0">fitignore</xsl:when>

    <xsl:when test="counts/wrong > 0" >fitfail</xsl:when>

    <xsl:otherwise>fitpass</xsl:otherwise>

    </xsl:choose>

    </xsl:variable>

    <div class="line">

    <span class="{$colorClass}" style="padding:2px;" ><xsl:value-of select="counts/right"/> right, <xsl:value-of select="counts/wrong"/> wrong,

    <xsl:value-of select="counts/ignores"/> ignored, <xsl:value-of select="counts/exceptions"/> exceptions </span>

    <span style="padding:2px;"><xsl:value-of select="relativePageName"/></span>

    </div>

    </xsl:for-each>

    </div>

    </xsl:when>

    </xsl:choose>

    </xsl:template>

    </xsl:stylesheet>

     

    Hook this Xsl into your CC.Net configuration, and that's as hard as it is!  FitNesse results "magically" show up in the build summary.  It's really a big win for visibility into the state of the software.  The build summary is now the actual status report of the software, and it's not subjective.  What does 83% actually mean?  With a list of acceptance tests to fulfill, we know exactly when we are done.


     

  • EZWeb demo site up and running - Go check it out!!! - level 000

    One of the things EZWeb is perfect for is a family website where every member has a section.  Go to http://palermofamily.com/ to check it out.

    This is a live demo site where several sub-pages have been set up for you to freely modify.  Just log in with user: joeUser, pass: joeUser, and you will be able to modify any of the Sandbox pages.

  • Response to EZWeb feedback - level 100

    Stefano, in this post, gives some feedback about EZWeb 1.2 release 2.  He has set up EZWeb on his server here.  Here is Stefano's comments (in italics) and my response.

    I've setup the site on this address on my server and I have to say that the project has totally reached its 2 main purposes:

    • Easy to install: you've only to copy on a virtual directory of your IIS server the content of the package and set a special permission to a directory and all is done.
    • Easy to edit contents: the site uses the FreeTextBox control to edit pages. You can easy create how many pages you want and edit content is so easy as writing a document with MS Word (so it's a task that can be improved also for a person that don't know nothing about HTML).

    However, this post is expecially to send feedback for future improvements, and I think that some more work must be done on these areas:

    • Site Templates: the templates that are present now on the package are really too much "poor". Why not working on a graphical template, with images and CSS? The site's appearance is not so good for eyes I think...

    I definitely agree with this one.  I've concentrated my efforts on the internal framework, so the templates are very basic.  Templates are just a simple UserControl that is almost exactly like v2.0 master pages.  It is very easy to modify the markup of any of the templates to alter the look of the site.  I've included the full source for all templates and plugins - which are both just user controls.  I do plan on adding more attractive templates to choose out of the box, and if anyone wants to contribute a template, I'll gladly include it.  With the advent of "Master Pages", we'll probably see online libraries of them.  It will be trivial to use any template or master page with EZWeb.

    • User Administration: adding a user to the site is really easy, but why not adding a more complete user interface, with the possibility to add user's data for example?

    I have big plans for my 2.0 version to coorespond with .Net 2.0, and one of the things is using the built-in User Management provider, so I didn't want to invest in a custom user management piece at this point.  Even so, user attributes would only make sense in a situation where you extend EZWeb with a control that makes use of these attributes, like a control that checks roles.  For this, you can create your own User class at this point and change the web.config to use your class.  Without custom development, user attributes don't make sense at this point, but I will comply with the Membership provider for my version 2.

    Now two personal requests to Jeffrey:

    • How can I change user's permission? If I want to create a user that has permissions to add pages just like an administrato, how can I do? I've not understood this...

    To change user permissions, click on "Manage Page" when logged in as "admin".  At the bottom of the screen, you see "Editors".  All the users should appear in the drop-down.  Click Add, and then select what permissions to delegate for the current page.  For most cases, allowing all permissions is best, but you can give EditContent permission only if you really want.  Click "update" in that row, and then click "Save".  Then, when logged in as that user, you can exercise that permission.  Permissions work down the web tree just like NTFS permission in the filesystem.  Permissions at the site root are inherited by all pages in the site. 

    • Is it possible to add a task list or a calendar feature to the site? I think that something like an "Outlook" calendar could be useful on a site like this.

    It is possible if you have a calendar ASP.NET web control.  Any web control can be invoked dynamically by any page.  Use the "Control Loader" plugin.  It can load a user control or custom control.  For this version, the Content Editor is the only plugin with a GUI.  EZWeb is expandable by adding web controls that do the functionality desired.  Code to all plugins is included in the download.  If anyone has a control that would be useful for EZWeb, I'll be happy to include it.

    Also, at some point, I think an EZWebContrib open source project might be useful for Templates, Plugins, and Themes.

  • EZWeb 1.2 release 2 available for download - level 000

    I've made a second release of version 1.2 on GotDotNet.  The reason for this is a bug in the configuration of FreeTextBox as well as simplification for hosting deployments.  GoDaddy has custom permission support for subfolders, but they don't allow custom permissions inside the aspnet_client directory, so I've modified the configuration so that writeable files are in a new directory, EZWebFiles, and this plays better with GoDaddy.  I can only assume that some others might not like to grant change access to aspnet_client. 

    The binaries haven't changed, just the configuration has.

    You can download it here.  I'm almost done with the EZWeb sandbox site, so in a bit, you all will be able to go to the sandbox and play.  I'll be using this site as well to compile some FAQs and the beginnings of documentation.  After all, EZWeb allows the editing of content very simply!

    If you've downloaded EZWeb and are using it for a community or personal site, put the word out.  Let everyone know how easy EZWeb is for getting a website up and running.

  • RealVNC works great for pair programming - level 200

    RealVNC has been around for a long time, and it is a great tool for remote control of a computer.  I remember using it on servers back in the WinNT days.  It runs as a windows service, so using the small client, you can connect from anywhere over port 5900 (the default).

    For pair programming, it's essential that both developers are comfortable in front of their own keyboard, mouse, and monitor.  You CAN use a single computer, but the developer who is reviewing has a bad angle on the screen and just generally isn't comfortable.  Another method is to attach two monitors, two keyboards and two mice to the same machine.  That would work (I've never done it), but after using RealVNC for two full days, I'm sold.  It doesn't require a special computer configuration, and it's super easy to get set up and working.  Your partner can know your VNC password, or (as I prefer), the partner turns on the listening client, and then I run the "Add a client" command, put in his computer name, and bingo!, we're connected.  We're running on my box, but do an F8 and Full Screen, and you can hardly tell the difference. 

    I just finished 3 straight days of pairing, and we used VNC on the last 2 days.  It works really well.

    VNC is also great for conference calls.  I was on a short conference call yesterday, and the folks on the other end needed to show us something.  I turned on my VNC listening client, they added me, and we had video!  Great tool!

    If you aren't already using it, download it now.  VNC goes beyond remote control well into collaboration.

More Posts Next page »

This Blog

Syndication