Skip Navigation LinksHome > SSW Standards > SSW Rules > Rules To Better .NET Projects

What others have to say about us
See what people think about this product I've been putting together Development Guidelines for my employer and in the process have reviewed many published standards (in the .Net arena) from around the world. In each category, the suggestions at SSW are always among the best. See what people think about this product
- Leon Bambrick,
 

Do you agree with them all? Are we missing some? Let us know what you think.

  1. Do you have a consistent .NET Solution Structure?
  2. Do you name your startup form consistently?
  3. Do you have a structured Solution Folders for your solution items?
  4. Do you always say "Option Strict On"?
  5. Do you keep clean on Imports of Project Property?
  6. Do you add the necessary code so you can always sync the web.config file?
  7. Do you avoid periods (.) in directory names?
  8. Do you name your assemblies consistently (<CompanyName>.<ComponentName>)?
  9. Do you use the designer for all visual elements?
  10. Do you refer to images the correct way in ASP .NET?
  11. Do you use Microsoft.VisualBasic in your VB.NET projects?
  12. Do you avoid Microsoft.VisualBasic.Compatibility in your VB.NET projects?
  13. Do you have a build/integration machine for shared components?
  14. Do you publish your components to Source Safe?
  15. Do you reference "most" .dlls by Project?
  16. Do you reference "very calm/stable" .dlls by Assembly?
  17. Do you keep your Assembly Version Consistent?
  18. Do you use configuration management application block?
  19. Do you have a resetdefault() function in your configuration? management application block?
  20. Do you hard code your ConnectionString?
  21. Do you make sure that the database structure is automatically handled automatically via 3 buttons "Create", Upgrade" and "Reconcile"?
  22. Do you version your .xml files?
  23. Are your settings and the customizable settings, in different files?
  24. Do you secure your web services using WCF over WSE3 and SSL?
  25. Do you let the adapter handle the connection for you?
  26. Do you Open your Connection in a Try Block?
  27. Do you have meaningless Catch blocks in your applications?
  28. Do you put one class per file?
  29. Do you use a DataAdapter insert rows into your database?
  30. Do you put all images in images folder?
  31. Do you keep \images folder image only?
  32. Do you put all your setup file in your setup folder?
  33. Do you deploy your applications correctly?
  34. Do you distribute a product in Release mode?
  35. Do you use more meaningful names than Hungarian short form?
  36. Do you know how to rename files that under SourceSafe control?
  37. Do you profile your code when optimising performance?
  38. Do you Add SSW Code Auditor, NUnit and Microsoft FxCop project files to your Solution?
  39. Do you know what files not to put into VSS?
  40. Do you use resource file for storing your static script?
  41. Do you know the changes on DateTime in .NET 2.0 and .NET 1.0/1.1
  42. Do you know how to use Connection String in .NET 2.0?
  43. Do you avoid using duplicate connection string in web.config?
  44. Do you use Windows Integrated Authentication connection string in web.config?
  45. Do you highlight strings in your code editor?
  46. Do you use PowerShell to run batch files in Visual Studio?
  47. Do you make an instructions at the beginning and improve it gradually for web projects?
  48. Do you always prefix SQL stored procedure names with the owner in ADO.NET code?
  49. Do you always make file paths @-quoted?
  50. Do you always use Option Explicit?
  51. Do you use Asynchronous method and CallBack when invoke web method?
  1. Do you have a consistent .NET Solution Structure?

    When developing a n-tiered software solution, we follow a standard solution structure. We have incorporated unit testing components, which is an integral part of the Extreme Programming development methodology, into our solution structure:

    Project Type Project Name Note
    Application Northwind
    Namespace: SSW.Northwind
    Folder: SSW\Northwind\Northwind\
    Output: Northwind.exe
     
    Class Library WindowsUI
    Namespace: SSW.Northwind.WindowsUI
    Folder: SSW\Northwind\WindowsUI\
    Folder: SSW\Northwind\WindowsUI\Components
    Folder: SSW\Northwind\WindowsUI\UnitTests
    Output: WindowsUI.dll
    We put all the forms in a separate project so we can run Unit Tests on the UI using reflection.
    Application ConsoleUI
    Namespace: SSW.Northwind.ConsoleUI
    Folder: SSW\Northwind\ConsoleUI\
    Folder: SSW\Northwind\ConsoleUI\Components
    Folder: SSW\Northwind\ConsoleUI\UnitTests
    Output: NorthwindConsole.exe
    Application WebUI
    Namespace: SSW.Northwind.WebUI
    Folder: SSW\Northwind\WebUI\
    Folder: SSW\Northwind\WebUI\Components
    Folder: SSW\Northwind\WebUI\UnitTests
    Output: SSW.Northwind.WebUI.dll
    Namespace: SSW.Northwind.WebUI.Reports
    Folder: SSW\Northwind\WebUI\Reports\
    Manually-based reports - e.g. using the DataGrid
    Namespace: SSW.Northwind.WebUI.Components
    Folder: SSW\Northwind\WebUI\Components\
    Part of WebUI. For .css and .ascx user controls
    Windows Service WindowsService
    Namespace: SSW.Northwind.WindowsService
    Folder: SSW\Northwind\WindowsService\Components
    Folder: SSW\Northwind\WindowsService\UnitTests
    Output: SSW.Northwind.WindowsService.dll
     
    RS Reports Reports
    Namespace: N/A
    Folder: SSW\Northwind\Reports
    Output: N/A
    Reporting Services
    Class Library IServices
    Namespace: SSW.Northwind.IServices
    Folder: SSW\Northwind\IServices
    Folder: SSW\Northwind\IServices\UnitTests
    Output: SSW.Northwind.IServices.dll
    WCF Services Interfaces
    Class Library Services
    Namespace: SSW.Northwind.Services
    Folder: SSW\Northwind\Services
    Folder: SSW\Northwind\Services\UnitTests
    Output: SSW.Northwind.Services.dll
    WCF Services Implementations
    Class Library Business
    Namespace: SSW.Northwind.Business
    Folder: SSW\Northwind\Business\
    Folder: SSW\Northwind\Business\Components
    Folder: SSW\Northwind\Business\UnitTests
    Output: SSW.Northwind.Business.dll
    This can be code-generated
    Class Library Domain
    Namespace: SSW.Northwind.Domain
    Folder: SSW\Northwind\Domain
    Folder: SSW\Northwind\Domain\UnitTests
    Output: SSW.Northwind.Domain.dll
    LINQ DBML - this can be generated using SQL Metal
    Class Library DataSets
    Namespace: SSW.Northwind.DataSets
    Folder: SSW\Northwind\DataSets\
    Folder: SSW\Northwind\DataSets\UnitTests
    Output: SSW.Northwind.DataSets.dll
    Strongly typed datasets - this can be code-generated
    Class Library DataAccess
    Namespace: SSW.Northwind.DataAccess
    Folder: SSW\Northwind\DataAccess\
    Folder: SSW\Northwind\DataAccess\Components
    Folder: SSW\Northwind\DataAccess\UnitTests
    Output: SSW.Northwind.DataAccess.dll
    This project will contain all the code and SQL statements used to access data from your backend. This project can be code-generated
    Class Library UnitTests
    Namespace: SSW.Northwind.UnitTests
    Folder: SSW\Northwind\UnitTests\
    Output: SSW.Northwind.UnitTests.dll
    Only need this project if you are not using reusable components and then you do not need UnitTests folders above
    Wise Setup Northwind
    Folder: SSW\Northwind\Setup\
    Output: SSWNorthwind_v1-11.exe
    Make an EXE in Wise intead of an MSI because it allows the application to be upgraded

    We have included the unit tests with the project the test is designed for together into one assembly for several reasons:

    • It provides a logical association between the test and the class it is designed to test, promoting consistency between the two.
    • Ease of management - we don't need to match test assembly with the actual assembly by file naming standards, the association is inherent.
    • There are less projects to compile in a solution.

    For common library project, project name will include the company prefix and solution name, this is so other internal solution can include the common library's project. This will help debugging and development processes.

    Project Type Project Name Note
    Class Library SSWCommon Business
    Namespace: SSW.Common.Business
    Folder: ..\SSW\Common\Business\
    Output: SSW.Common.Business.dll
    No space in the Project Name

    For project documents, we will also add them into solution for later reference, and different document types will be put in different folder, e.g. Artworks' files will be in SSW\Documents\ArtWorks\

    Project Type Project Name Note
    Documents Documents
    Folder: SSW\Documents\
    This is outside the solution trunk
  2. Do you name your startup form consistently?

    In every Windows application project. We need to have a main form for a better structure and design.

    Bad Project without Main Form
    Bad example - The entry form is not immediately recognizable because of a non standard name
    Good with Main Form
    Good example - The entry form follows the naming convention rule
    We have a program called SSW Code Auditor to check for this rule.

    Note: In Code Auditor we check for Form named: Startup, MainService, MainForm and WizardPage.

  3. Do you have a structured Solution Folders for your solution items?

    All the DLL references and files needed to create a setup.exe will be included in your solution. However, just including them as solution items isnt enough, they will look very disordered (especially when you have a lot of solution items). And from the screenshot below, you might be wondering what the _Instructions.txt is used for...

    unstructured solution folder
    Bad example - An unstructured solution folder

    An ideal way is to create "sub-solution folders" for the solution items, the common ones are "References" and "Setup". This feature is only available in Visual Studio 2005. This will make your solution items look neat and in order. Look at the screenshot below, now it makes sense, we know that the _Instructions.txt contains the instructions of what to do when creating a setup.exe.

    A well structured solution folder has 2 folders - "References" and "Setup"
    Good example - A well structured solution folder has 2 folders - "References" and "Setup"
    We have a program called SSW Code Auditor to check for this rule.
  4. Do you always say "Option Strict On"?

    Fixing the Option Strict problem One of the most annoying aspects of the Visual Basic development environment relates to Microsofts decision to allow late binding. By turning Option Strict Off by default, many type-casting errors are not caught until runtime. You can make VB work the same as other MS languages (which always do strict type-checking at design time) by modifying these templates.

    So, always set Option Strict On right from the beginning of the development.

    Before you do this, you will first back up the entire VBWizards directory. If you make a mistake, then the templates will not load in the VS environment. You need to be able to restore the default templates if your updates cause problems.

    To configure each template to default Option Strict to On rather than Off, load each .vbproj template with VB source code into an editor like Notepad and then change the XML that defines the template. For example, to do this for the Windows Application template, load the file: Windows Application\Templates\1033\WindowsApplication.vbproj

    under the VBWizards directory into Notepad and find the settings Element. You will see something like this:

    <VisualStudioProject>

    <VisualBasic>

    <Build>

    <Config . . . .

    Now, add the following lines under OutputType: OptionStrict = "On" OptionExplicit = "On"

    Or you go to Project property page as you can see the snapshot below and change to Option Strict = "On", OptionExplicit = "On".

    Option Strict On

    Technically, you do not have to add the Option Explicit directive, because this is the default for VB; but I like to do it for consistency. Next, you must save the file and close Notepad. Now, if you load a new Windows Application project in the VS environment and examine Project Properties, you will see that Option Strict has been turned on by default.

    In order for this setting to take effect for all project types, you must update each of the corresponding .vbproj templates. After making the changes on your system, youll need to deploy the new templates to each of your developers' machines in order for their new projects to derive from the updated templates.

    However, sometimes we don't do this because of too much work. In some scenarios, such as Wrappers around the COM code, and Outlook stuff with object model, there is going to be lots of work to fix all the type-checking errors. Actually it is necessary to use Object type as parameters or variables when you deal with COM components.

    .NET Standards in ZDNetYou are going to a site outside of SSW

     

  5. Do you keep clean on Imports of Project Property?

    When programming in a Dot Net environment it is a good practice to remove the default imports that aren't used frequently in your code.

    This is because IntelliSense lists will be harder to use and navigate with too many imports. For example if in VB.NET, Microsoft.VisualBasic would be a good item to have in the imports list, because it will be used in most areas of your application.

    To remove all the default imports, load Project Property page and select Common properties - Imports.

    Imports VB
    Using Aliases with the Imports Statement :

    The Imports statement makes it easier to access methods of classes by eliminating the need to explicitly type the fully qualified names of references. Aliases let you assign a friendlier name to just one part of a namespace.

    For example, the carriage return-line feed sequence that causes a single piece of text to be displayed on multiple lines is part of the ControlChars class in the Microsoft.VisualBasic namespace. To use this constant in a program without an alias, you would need to type the following code:

    MsgBox("Some text" & Microsoft.VisualBasic.ControlChars.crlf _ &
                                "Some more text")
    Imports statements must always be the first lines immediately following any Option statements in a module. The following code fragment shows how to import and assign an alias to the Microsoft.VisualBasic.ControlChars namespace:

    Imports CtrlChrs=Microsoft.VisualBasic.ControlChars
    Future references to this namespace can be considerably shorter:

    MsgBox("Some text" & CtrlChrs.crlf & "Some more text")
    If an Imports statement does not include an alias name, elements defined within the imported namespace can be used in the module without qualification. If the alias name is specified, it must be used as a qualifier for names contained within that namespace.
    Figure: Using aliases with the Imports Statement
  6. Do you add the necessary code so you can always sync the web.config file?

    The Web.config file will be your main source where you store your application settings. These change, depending on which system you are working on, e.g. your local machine or the website. That's why you have to keep two versions of the Web.config file, one for your local machine and one for the website.
    That's annoying, not really efficient and often the cause of problems.

    In the following extract of a sample Web.config file you can see the problem. The local machine "HIPPO" has, of course, another WebServiceURL than the Webserver "SEAL". So you have to keep two versions of the Web.config file, one when working on "HIPPO" and one when working on "SEAL".

    <add key="SEAL_WebServiceURL" value="http://host.something.com:80/SomeDirectory/Filename.asmx"/>
    <add key="HIPPO_WebServiceURL"value="http://name:80/SomeDirectory/Filename.asmx"/>
    Figure: Sample Web.config file

    There is a better solution:

    Public Shared Function GetWebConfigString(ByVal StringName As String) As String
        Dim strReturn As String = ""
        Dim strComputerName As String = System.Net.Dns.GetHostName
        Try
            strReturn = ConfigurationSettings.AppSettings( strComputerName.ToUpper + "_"+ StringName)
        Catch
            strReturn = ConfigurationSettings.AppSettings(StringName)
        End Try
    Return strReturn
    End Function
    Figure: Sample Get WebConfigString Class

    This class simply adds the name of the Computer on which it is running on to the WebConfigString. In the former example, this would be "HIPPO_" or "SEAL_".

    Instead of using the WebConfigString directly you can now transform it using this function. With the help of this code, you always get the right value for the WebConfigString, no matter on which machine the application runs and you don't have to care about synchronizing the Web.config file any more.


  7. Do you avoid periods (.) in directory names?

    We've elected to not allow periods in directory name, primarily because it creates problems with Windows' auto-complete intellisense.

    C:\Bad.Example.With.Periods\
    Figure: Bad example of directory name with periods (.)

    C:\Good Example Without Periods\
    Figure: Good example of directory name without periods (.)

    We have a program called SSW Code Auditor to check for this rule.
  8. Do you name your assemblies consistently (<CompanyName>.<ComponentName>)?

    Assembly names will reflect the the functionality that it provides. For example,

    System.IO

    contains all the classes that deal with inputs and outputs. As a general rule of thumb your assemblies will be named as follows:

    <CompanyName>.<ComponentName> (e.g. SSW.Framework)

    This allows a developer to know who developed the assembly and give the developer a general idea of what the assembly can be used for.

  9. Do you use the designer for all visual elements?

    The designer will be used for all GUI design. Controls will be dragged and dropped onto the form and all properties will be set in the designer, e.g.

    • Labels, TextBoxes and other visual elements
    • ErrorProviders
    • DataSets (to allow data binding in the designer)

    Things that do not belong in the designer:

    • Connections
    • Commands
    • DataAdapters

    However, and DataAdapter objects will not be dragged onto forms, as they belong in the business tier. Strongly typed DataSet objects will be in the designer as they are simply passed to the business layer. Avoid writing code for properties that can be set in the designer.

    Bad example - Connection and Command objects in the Designer
    Good example - Only visual elements in the designer
  10. Do you refer to images the correct way in ASP .NET?

    There are many ways to reference images in ASP.NET. There are two different situations commonly encountered by developers when working with images:

    • Scenario #1: Images that are part of the content of a specific page eg. a picture used only on one page
    • Scenario #2:Images that are shared across on user controls which are shared across different pages in a site eg. a shared logo used across the site (commonly in user controls, or master pages)

    Each of these situations requires a different referencing method.

    Option #1:Absolute Paths (Root-Relative Paths)
    Often developers reference all images by using an absolute path (prefixing the path with a slash, which refers to the root of the site), as shown below.

                            <img src="/Images/spacer.gif" height="1" width="1">
    Bad example - Referencing images with absolute paths

    This has the advantage that <img> tags can easily be copied between pages, however it will not be used in either situation, because it requires that the website have its own site IIS and be placed in the root (not just an application), or that the entire site be in a subfolder on the production web server. For example, the following combinations of URLs are possible with this approach:

    Staging Server URL Production Server URL
    http://bee:81/ http://www.ssw.com.au/
    http://bee/ssw/ http://www.ssw.com.au/ssw/

    As shown above, this approach makes the URLs on the staging server hard to remember, or increases the length of URLs on the production web server.

    Verdict for Scenario #1:

    Verdict for Scenario #2:

    Option #2:Relative Paths
    Images that are part of the content of a page will be referenced using relative paths, e.g.

                            <img src="../Images/spacer.gif" height="1" width="1">
    Good example - Referencing images with absolute paths.

    However, this approach is not possible with images on user controls, because the relative paths will map to the wrong location if the user control is in a different folder to the page.

    Verdict for Scenario #1:

    Verdict for Scenario #2:

    Option #3:Application-Relative Paths
    In order to simplify URLs, ASP.NET introduced a new feature, application relative paths. By placing a tilde (~) in front of a path, a URL can refer to the root of a site, not just the root of the web server. However, this only works on Server Controls (controls with a runat="server" attribute).

    To use this feature, you need either use ASP.NET Server controls or HTML Server controls, as shown below.

                            <asp:Image ID="spacerImage" ImageUrl="~/Images/spacer.gif"
                            Runat="server" />
    <img id="spacerImage" src="~/Images/spacer.gif" runat="server">
    Good example - Application-relative paths with an ASP.NET Server control
    Using an HTML Server control creates less overhead than an ASP.NET Server control, but the control does not dynamically adapt its rendering to the user's browser, or provide such a rich set of server-side features.

    Verdict for Scenario #1:

    Verdict for Scenario #2:

    Note:A variation on this approach involves calling the Page.ResolveUrl method with inline code to place the correct path in a non-server tag.

                            <img src='<%# Page.ResolveUrl("~/Images/spacer.gif") %>'>
                        
    Bad example - Page.ResolveUrl method with a non-server tag

    This approach is not recommended, because the data binding will create overhead and affect caching of the page. The inline code is also ugly and does not get compiled, making it easy to accidentally introduce syntax errors.

    We have a program called SSW Code Auditor to check for this rule.

  11. Do you use Microsoft.VisualBasic.dll for Visual Basic.NET projects?


    The Microsoft.VisualBasic library is provided to ease the implementation of the VB.NET language itself. For VB.NET, it provides some methods familiar to the VB developers and can be seen as a helper library. It is a core part of the .NET redistribution and maps common VB syntax to framework equivalents, without it some of the code may seem foreign to VB programmers.
    Microsoft.VisualBasic .NET Framework
    CInt, CStr Convert.ToInt(...), ToString()
    vbCrLf Environment.NewLine, or "\r\n"
    MsgBox MessageBox.Show(...)

  12. Do you avoid Microsoft.VisualBasic.Compatibility.dll for Visual Basic.NET projects?

  13. This is where you will focus your efforts on eliminating whatever VB6 baggage your programs or developer habits may carry forward into VB.NET. There are better framework options for performing the same functions provided by the compatibility library You will heed this warning from the VS.NET help file: Caution: It is not recommended that you use the VisualBasic.Compatibility namespace for new development in Visual Basic .NET. This namespace may not be supported in future versions of Visual Basic. Use equivalent functions or objects from other .NET namespaces instead.? ad.?

    Avoid:

    • InputBox
    • ControlArray
    • ADO support in Microsoft.VisualBasic.Compatibility.Data
    • Environment functions
    • Font conversions
     
  14. Do you have a build/integration machine for shared components?

    There will be one compiled set of shared components.

  15. Do you publish your components to Source Safe?

    Incrementally as we do more and more .NET projects, we discover that we are re-doing a lot of things we've done in other projects. How do I get a value from the config file? How do I write it back? How do I handle all my uncaught exceptions globally and what do I do with them?

    Corresponding with Microsoft's release of their application blocks, we've also started to build components and share them across projects.

    Sharing a binary file with SourceSafe isn't a breeze to do, and here are the steps you need to take. It can be a bit daunting at first.

    As the component developer, there are four steps:

    1. In Visual Studio.NET, Switch to release build
      Build Release
      Figure: Switch to release configuration

    2. In your project properties, make sure the release configuration goes to the bin\Release? folder. While you are here, also make sure XML docs are generated. Use the same name as your dll but change the extension to .xml (eg. for SSW.Framework.Configuration.dll -> add SSW.Framework.Configuration.xml)
      Build Project Property
      Figure: Project properties

      Note: The following examples are considered being used for C#. Visual Basic, by default, does not have \bin\Release and \bin\Debug which which means that the debug and release builds will overwrite each other unless the default settings are changed to match C# (recommended). VB does not support XML comments either, please wait for the next release of Visual Studio (Whidbey).

      Change to C#
      Figure: Force change to match C#

       

    3. If this is the first time, include/check-in the release directory into your SourceSafe
      Build Include
      Figure: Include the bin\Release directory into source safe

    4. Make sure everythings checked-in properly. When you build new versions, switch to Release?mode and checkout the release dlls, overwrite them, and when you check them back in they will be the new dll shared by other applications.

    5. If the component is part of a set of components, located in a solution, with some dependency between them. You need to check out ALL the bin\Release folders for all projects in that solution and do a build. Then check in all of them. This will ensure dependencies between these components don't conflict with projects that reference this component set.

      In other words, a set of components such as SSW.Framework.WindowsUI.xxx, increment versions AS A WHOLE. One component in this set changes will cause the whole set to re-establish internal references with each other.



  16. Do you reference "most" .dlls by Project?

  17. When you obtain a 3rd party .dll (in-house or external), you sometimes get the code too. So will you:

    • reference the Project (aka including the source) or
    • reference the assembly?

    When you face a bug, there are 2 types of emails you can send:
    1. Dan, I get this error calling your Registration.dll? or
    2. Dan, I get this error calling your Registration.dll and I have investigated it. As per our conversation, I have changed this xxx to this xxx.

    The 2nd option is preferable.

    The simple rule is:
    If there are no bugs then reference the assembly, and
    If there are bugs in the project (or any project it references [See note below]) then reference the project.
    Since most applications have bugs, therefore most of the time you will be using the second option.
    If it is a well tested component and it is not changing constantly, then use the first option.

    1. Add the project to solution (if it is not in the solution).
    2. Add existing project
      Figure: Add existing project

    3. Select the "References" folder of the project you want to add references to, right click and select "Add Reference...".

    4. Add reference
      Figure: Add reference

    5. Select the projects to add as references and click OK.
    6. Select projects to reference
      Figure: Select the projects to add as references
    Note: We have run into a situation where we reference a stable project A, and an unstable project B. Project A references project B. Each time project B is built, project A needs to be rebuilt.
    Now, if we reference stable project A by dll, and unstable project B by project according to this standard, then we might face referencing issues, where Project A will look for another version of Project B ?the one it is built to, rather than the current build, which will cause Project A to fail.
    To overcome this issue, we then reference by project rather than by assembly, even though Project A is a stable project. This will mitigate any referencing errors.
  18. Do you reference "very calm/stable" .dlls by Assembly?

    If we lived in a happy world with no bugs, I would be recommending this approach of using shared components from source safe. As per the prior rule, you can see we like to reference "most" .dlls by project.
    However if you do choose to reference a .dll without the source, then the important thing is that if the .dll gets updated by another developer, then there is *nothing* to do for all other developers ?they get the last version when they do your next build. Therefore you need to follow this:


    As the component user, there are six steps, but you only need to do them once:
    1. First, we need to get the folder and add it to our project, so in SourceSafe, right click your project and create a subfolder using the Create Project (yes, it is very silly name) menu.
      Use Create VSS Folder
      Figure: Create 'folder' in Visual Source Safe

      Name it References
      Use References Folder
      Figure: 'References' folder

    2. Share the dll from the directory, so if I want SSW.Framework.Configuration, I go to $/ssw/SSWFramework/Configuration/bin/Release/
      I select both the dll and the dll.xml files, right-click and drag them into my $/ssw/zzRefs/References/ folder that I just created in step 1.
      Use Dlls Xml
      Figure: Select the dlls that I want to use
      Use right click to share
      Figure: Right drag, and select "Share"

    3. Still in SourceSafe, select the References folder, run get latest?to copy the latest version onto your working directory.
      Use Get Latest
      Figure: Get Latest from Visual Source Safe
      VSS may ask you if you want to create the folder, if it doesnt exist. Yes, we do.
    4. Back in VS.NET, select the project and click the show-all files button in the solution explorer, include the References folder into the project (or get-latest if its already there)
      Use Include Invs
      Figure: Include the files into the current project
    5. IMPORTANT! If the files are checked-out to you when you include them into your project, you MUST un-do checkout immediately.
      You will never check in these files, they are for get-latest only.
      Use Undo Checkout
      Figure: Undo Checkout, when VS.NET checked them out for you...
    6. Add Reference?in VS.NET, browse to the References?subfolder and use the dll there.
    7. IMPORTANT! You need to keep your 'References' folder, and not check the files directly into your bin directory. Otherwise when you 'get latest', you won't be able to get the latest shared component.

    All done. In the future, whenever you do get-latest?on the project, the any updated dlls will come down and be linked the next time you compile. Also, if anyone checks out your project from Source Safe, they will have the project linked and ready to go.

  19. Do you keep your Assembly Version Consistent?

    It is important to keep Assembly version and Assembly file version consistent, otherwise it can lead to support and maintenance nightmares. By default these version values are defined in the AssemblyInfo file. In the following examples, the first line is the version of the assembly and the second line is the actual version display in file properties.

    [assembly: AssemblyVersion("2.0.*")]
    [assembly: AssemblyFileVersionAttribute("1.0.0.3")]
    Bad example - the common assembly versioning method.
    [assembly: AssemblyVersion("2.0.*")]
    [assembly: AssemblyFileVersionAttribute("2.0.*")]
    Good example - the best way for Assembly versioning.
  20. Do you use configuration management application block?

    How do you get a setting from a configuration file? What do you do when you want to get a setting from a registry, or a database? Everyone faces these problems, and most people come up with their own solution. We used to have a few different standards, but when Microsoft released the Configuration Application Blocks, we have found that working to extend it and use it in all our projects saves us a lot of time! Use a a local configuration file for machine and/or user specific settings (such as a connection string), and use a database for any shared values such as Tax Rates.

    See how we configured this reset default settings functionality with the Configuration Block in the .NET Toolkit



  21. Do you have a resetdefault() function in your configuration management application block?

    In almost every application we have a user settings file to store the state of the application. We want to be able to reset the settings if anything goes wrong.

    See how we configured this reset default settings functionality with the Configuration Block in the .NET Toolkit



  22. Do you hard code your ConnectionString?

    We don't like hard coded string inside our programme. We are using model-driven development, in which we create or reuse code, and perform changes in configuration file rather the in-code changing. More information on implementing our configuration.

                            connection.ConnectionString = "
    Provider=SQLOLEDB;
                                
    Data Source=server_name_or_address; Initial Catalog=database_name;
    User ID=username; Password=password;
    ";

    connection.Open();

    Bad code - use the lengthy connection string.
                            connection.ConnectionString = ConfigurationManager.Items["ConnectionString"];
    connection.Open();
    Figure: Good Code - Use ConfigurationManager to handle the connection string.

     

    We have a program called SSW Code Auditor to check for this rule.

  23. Do you make sure that the database structure is automatically handled automatically via 3 buttons "Create", Upgrade" and "Reconcile"?

    You get an error message reported from a user like:

    When I click the Save button on the product form it gives an error message about a missing field.

    You try and reproduce it on your version in the office and everything works perfectly, you suspect that the customer probably has changed the schema. So you start drafting an email to the user like:

    Mary, I need you to send me your database schema as it might be different from what it will be. Can you:
    1. Open up Enterprise Manager (or SQL Management Studio)
    2. Open the first tree
    3. Open the second tree
    4. Select your server
    5. Open that tree
    6. Select Databases
    7. Open that tree
    8. Select the database called Northwind
    9. Right click it and choose All Tasks, then Generate SQL Script
    10. Then select the options
    11. etc
    12. Then when I get this I will compare and I will make a script file for you to run and fix the problem

    STOP! STOP! STOP!
    It would be much better to just say:

    Mary, click the "Reconcile" button and it will tell us what is wrong

    Bottom line is the customers' database schema will always be correct and this will be managed automatically by the application.

    Therefore, we always deliver an application with the buttons "Create", Upgrade" and "Reconcile", accessible via "Tools - Options" and a "Database" tab. We do this by using SSW SQL Deploy and throwing on the inherited user-control from the SSW.SQLDeploy.Options project.

    For more information see Best Tools for SQL Server

    It looks like this
    Reconcile
    Figure: Showing the "Reconcile" which compares the current scripts with the Clients database; and the "Upgrade" which will run the scripts that have been most recently included in the latest version for the client.

    On clicking "Select" another Dialog will open with the required functions for creating a database or using an existing one as shown below:

    New database dialog

    Figure: Creating a New database for the client if there is no database to begin with.

     
  24. Do you version your .xml files?

    It is good to store program settings in an .xml file. But developers rarely worry about future schema changes and how they will inform the user it is an old schema.

    What is wrong with this?

    <?xml version="1.0" standalone="yes"?>
    <NewDataSet>
        <xs:schema id="NewDataSet" xmlns=""
            xmlns:xs="http://www.w3.org/2001/XMLSchema"
            xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
                <xs:element name=NewDataSet" msdata:IsDataSet="true" msdata:Locale="en-AU">
                    <xs:complexType>
                        <xs:choice maxOccurs="unbounded">
                            <xs:element name="Table1">
                                <xs:complexType>
                                    <xs:sequence>
                                        <xs:element name="DateUpdated" type="xs:dateTime" minOccurs="0" />
                                        <xs:element name="NewDatabase" type="xs:boolean" minOccurs="0" />
                                        <xs:element name="ConnectionString" type="xs:string" minOccurs="0" />
                                        <xs:element name="SQLFilePath" type="xs:string" minOccurs="0" />
                                        <xs:element name="TimeOut" type="xs:int" minOccurs="0" />
                                        <xs:element name="TurnOnMSDE" type="xs:boolean" minOccurs="0" />
                                        <xs:element name="KeepXMLRecords" type="xs:boolean" minOccurs="0" />
                                        <xs:element name="UserMode" type="xs:boolean" minOccurs="0" />
                                        <xs:element name="ReconcileScriptsMode" type="xs:boolean" minOccurs="0" />
                                        <xs:element name="FolderPath" type="xs:string" minOccurs="0" /> />
                                        <xs:element name="SelectedFile" type="xs:string" minOccurs="0" />
                                        <xs:element name="UpdateVersionTable" type="xs:boolean" minOccurs="0" />
                                    </xs:sequence>
                                </xs:complexType>
                            </xs:element>
                        </xs:choice>
                    </xs:complexType>
                </xs:element>
        </xs:schema>

        <Table1>
            <DateUpdated>2004-05-17T10:04:06.9438192+10:00</DateUpdated>
            <NewDatabase>true</NewDatabase>
            <ConnectionString>Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Data Source=(local);Initial Catalog=master</ConnectionString>
            <SQLFilePath>ver0001.sql</SQLFilePath>
            <TimeOut>5</TimeOut>
            <TurnOnMSDE>false</TurnOnMSDE>
            <KeepXMLRecords>false</KeepXMLRecords>
            <UserMode>true</UserMode>
            <ReconcileScriptsMode>true</ReconcileScriptsMode>
            <FolderPath>C:\Program Files\SSW SQL Deploy\Samples\DatabaseSQLScripts\</FolderPath>
            <SelectedFile />
            <UpdateVersionTable>true</UpdateVersionTable>
        </Table1>
    </NewDataSet>
    Bad example - XML file without version control.
    <?xml version="1.0" standalone="yes"?> 
    <NewDataSet>
        <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http:/www.w3.org/2001/XMLSchema"
            xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
                <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:Locale="en-AU">
                    <xs:complexType>
                        <xs:choice maxOccurs="unbounded">
                            <xs:element name="Table1">
                                <xs:complexType>
                                    <xs:sequence>
                                        <xs:element name="Version" type="xs:string" minOccurs="0" />
                                        <xs:element name="DateUpdated" type="xs:dateTime" minOccurs="0" />
                                        <xs:element name="NewDatabase" type="xs:boolean" minOccurs="0" />
                                        <xs:element name="ConnectionString" type="xs:string" minOccurs="0" />
                                        <xs:element name="SQLFilePath" type="xs:string" minOccurs="0" />
                                        <xs:element name="TimeOut" type="xs:int" minOccurs="0" />
                                        <xs:element name="TurnOnMSDE" type="xs:boolean" minOccurs="0" />
                                        <xs:element name="KeepXMLRecords" type="xs:boolean" minOccurs="0" />
                                        <xs:element name="UserMode" type="xs:boolean" minOccurs="0" />
                                        <xs:element name="ReconcileScriptsMode" type="xs:boolean" minOccurs="0" />
                                        <xs:element name="FolderPath" type="xs:string" minOccurs="0" />
                                        <xs:element name="SelectedFile" type="xs:string" minOccurs="0" />
                                        <xs:element name="UpdateVersionTable" type="xs:boolean" minOccurs="0" />
                                    </xs:sequence>
                                </xs:complexType>
                            </xs:element>
                        </xs:choice>
                    </xs:complexType>
                </xs:element>
        </xs:schema>

    <Table1>
    <Version>1.2</Version>
    <DateUpdated>2004-05-17T10:04:06.9438192+10:00</DateUpdated>
    <NewDatabase>true</NewDatabase>
    <ConnectionString>Provider=SQLOLEDB;Integrated Security=SSPI;Data Source=(local);Initial Catalog=master</ConnectionString>
    <SQLFilePath>ver0001.sql</SQLFilePath>
    <TimeOut>5</TimeOut>
    <TurnOnMSDE>false</TurnOnMSDE>
    <KeepXMLRecords>false</KeepXMLRecords>
    <UserMode>true</UserMode>
    <ReconcileScriptsMode>true</ReconcileScriptsMode>
    <FolderPath>C:\Program Files\SSW SQL Deploy\Samples\DatabaseSQLScripts\</FolderPath>
    <SelectedFile />
    <UpdateVersionTable>true</UpdateVersionTable>
    </Table1>
    </NewDataSet>
    Figure: XML file with version control

    The version tags identifies what version the file is. This version will be hard coded into the application. Every time you change the format of the file, you would increment this number.

    The code below shows how this would be implemented in your project.

    Public Function IsXMLFileValid() As Boolean

        Dim fileVersion As String = "not specified"
        Dim dsSettings As New DataSet
        Dim IsMalformed As Boolean = False ' Is the file malformed all together with possibly version

        Try
            dsSettings.ReadXml(mXMLFileInfo.FullName, XmlReadMode.ReadSchema)
            Catch ex As Exception
            IsMalformed = True
        End Try

        If (Not IsMalformed) Then
            Dim strm As Stream = Asm.GetManifestResourceStream(Asm.GetName().Name + "." + "XMLFileSchema.xsd")
            Dim sReader As New StreamReader(strm)
            Dim dsXMLSchema As New DataSet
            dsXMLSchema.ReadXmlSchema(sReader)

            If dsSettings.Tables(0).Columns.Contains("Version") Then
                fileVersion = dsSettings.Tables(0).Rows(0)("Version").ToString
            End If

            If fileVersion = "" Then
                fileVersion = "not specified"
            End If

            If fileVersion = Global.XMLFileVersion AndAlso Not dsSettings.GetXmlSchema() = dsXMLSchema.GetXmlSchema() Then
                Return False
            End If

        End If

        If IsMalformed OrElse fileVersion <> Global.XMLFileVersion Then

            If mwillConvertFile Then
                ' Convert the file
                ConvertToCurrentVersion(IsMalformed)
            Else
                Throw New XMLFileVersionException(fileVersion, Global.XMLFileVersion )
            End If

        End If

        Return True

    End Function
    Figure: Code to illustrate how to check if the xml file is valid.

    Note: to allow backward compatibility, you will give the user an option to convert old xml files into the new version structure.

  25. Are your settings and the customizable settings, in different files?

    There are three types of settings files that we may need to use in .NET

    1. App.Config/Web.Config is the default .NET settings file, including any settings for the Microsoft Application Blocks (eg. the Exception Management Block and the Configuration Management Block). These are for settings that dont change from within the application. In addition, System.Configuration classes dont allow writing to this file.
    2. ToolsOptions.Config (an SSW standard) is the file to hold the users own settings, that are users can change in the Tools - Options.
      Eg. ConnectionString, EmailTo, EmailCC
      Note: We read and write to this using Microsoft Configuration Application Block. If we dont use this Block we would store it as a plain XML file and read and write to it using System.XML classes. The idea is that if something does go wrong when you are writing to this file, at least the App.Config would not be affected. Also, this separates our settings (which are few) from the App.Config (which usually has a lot of stuff that we really dont want a user to stuff around with).
    3. UserSession.Config (an SSW standard). These are for additional setting files that the user can not change.
      e.g. FormLocation, LastReportSelected
      Note: This file is over writable (say during a re-installation) and it will not affect the user if the file is deleted.                                                      &