Finding assembly information of an asp.net website

Getting near release time of a n-tiered system with multiple applications accessing the BLL/DAL framework? You want to make sure that what you think you're accessing really is the version you think it is. Using the AppDomain, you can get and parse through the assemblies and find a particular attribute match. In the case below, I'm looking for the companyname. I put this into a user control and applications can use it in a "help" or "about" page. This has come in handy for me, when you realize you've not updated your referenced or the GAC assembly. The key for asp.net apps is to add the App_Code folder and put an AssemblyInfo.cs file with the proper assembly information in it. (You DO need to remember to update that).

the aspx code-
   <asp:Repeater ID="Assemblyrptr" runat="server">
        <headertemplate>
        Assemblies:<br />
        </headertemplate>
        <itemtemplate>
        <%#Container.DataItem%>
        <br />
        </itemtemplate>

    </asp:Repeater>

the code behind C#-
    protected void Page_Load(object sender, EventArgs e)
    {
        AppDomain currentDomain = AppDomain.CurrentDomain;
        //Load the assembly from the application directory using a simple name.
        //Make an array for the list of assemblies.
        Assembly[] assems = currentDomain.GetAssemblies();
        List<Assembly> appassemlist = assems.ToList<Assembly>();
        List<string> assemList = new List<string>();
        foreach (Assembly appassem in appassemlist)
        {
            AssemblyCompanyAttribute mdtName = (AssemblyCompanyAttribute)Attribute.GetCustomAttribute(appassem, (typeof(AssemblyCompanyAttribute)));
            if (mdtName != null && mdtName.Company.StartsWith("yourcompanynamehere"))
                assemList.Add(appassem.FullName);
        }
        Assemblyrptr.DataSource = assemList;
        Assemblyrptr.DataBind();

    }


On a different subject but, same idea, you can grab the asp.net app_code assembly, stuff it in cache and use it in the master page footer.

    void Application_Start(object sender, EventArgs e)
    {
        // Code that runs on application startup
        log4net.Config.XmlConfigurator.Configure();
        AppDomain currentDomain = AppDomain.CurrentDomain;
        //Load the assembly from the application directory using a simple name.
        //Make an array for the list of assemblies.
        Assembly[] assems = currentDomain.GetAssemblies();
        Assembly myassm = this.GetType().Assembly;
        int i = 0;
        for (i = 0; i < assems.Length; i++ )
        {
            if (assems[i].FullName.StartsWith("Deploy") || assems[i].FullName.StartsWith("App_Code") )
            {
                myassm = assems[i];
                Application.Add("Assembly", myassm);
                break;
            }
        }
       //This is another way to do it - this works too.
        //Application.Add("Assembly", System.Reflection.Assembly.Load("App_Code/AssemblyInfo.cs"));

    }

Checkin' Out Live Writer with Subtext

Installed livewriter, so I just pitched some stories about my dog, and playing around with Telerik's TreeView control. Mostly just to see how pictures, code, and web controls look. If you find any of this useful, you've got problems.

Technical Software Project Management is Dead

I’ve manage projects, I’ve lead them, I’ve been a developer, I’ve tested, I’ve organized releases, I’ve done all the paperwork. It’s just that lately, that seems to be the role expected from the developer on any given project. Beyond the sadistic boss, I've developed a theory on why this is occurring and why it won't stop...

LINQtoSQL Practical Best Practices

I don’t profess to be an expert. But I have been using this technology in my current project. The typical, understaffed, hurry up and learn, show me something, release it (and yes it must be validated, but doing so is your problem). Here’s what I’ve picked up while  coding shotgun style.

 

  1. Table names and Field names should always be different. When table names and field names are the same, LINQtoSQL renames the field name with a name1. Then when you have a table with a field name that’s a foreign key to another table and the foreign key matches the table name, which has a matching field. Don’t go there, even if LINQtoSQL gets it correct, you won’t.
  2. Keep the database names the same between the development, test, and production databases. The default connection string embeds the database name in it. Typically, I think it’s good practice to pass the connection string (that’s defined in the .config file) when creating the datacontext. The problem lies when you mix linqdatasources with business classes, the linqdatasource creates the datacontext with no parameters and lies on the internally generated connectionstring name. This is dependent on the database names and  you have a problem. Business methods pointing one way, linqdatasources pointing another way. The simple solution, just use business methods or just use linqdatasources. However, I still find that linqdatasource is great for the quick and dirty read. It gives you all the bells and whistles, but when it comes to updates, creation, deletion, I like to have my say in exactly what happens.
  3. When in doubt recreate the whole dbml, adding and deleting tables individually may effect relationships. This may be a product of my own confusion, but considering how nicely VS2008 creates the classes for you, use it. One or all, it’s drag and drop, do them all and be done with it.
  4. Extend classes in external files named after the original class.  Put extended class files in a separate folder. The partial classes are great. This just helps to keep things sorted. I’m waiting to read about somebody extending the LINQtoSQL classes to contain all their business rules. I think it’s possible for given scenarios. Could be interesting.

Using LinqToSQL LinqDataSource across multiple tables

I’ve been recently using LinqToSQL with a current project and finally got down to business where I needed to work with fields from multiple tables. LinqToSQL is nice, but it does have it’s drawback that it maps objects directly to the schema. Fortunately, it maps their relationships too. Let’s avoid the discussion of LinqToSQL pros and cons for now and figure out handling multi-table fields.

Did I mention I’m using the LinqDataSource? Oops… that too. I’m not a fan of the built in sqldatasource and linqdatasource, but when you’re prototyping they’re a great way to get something up and running (save the business logic layer for when you actually HAVE logic). The catch is, they tend to do a bit more than what you want them to. This is the case I stumbled into.

Getting to fields from related tables requires that you understand the underlying LinqToSQL classes. Once you have those, it’s just a matter of typing in the <%# Eval("blah.blah”) %> statement.

An example of this has been done and written up nicely by Todd Anglin- Todd's blog

In my case I have a primary key, PackageTestSystemID,  for a join table holding PKs to 2 other tables – PackageVersion and TestSystem. Displaying PKs is not user friendly, so I use the Eval statement to get the PackageName, Revision, and TestSystemSerial from the related tables. Shown below.

<Columns>

    <telerik:GridBoundColumn DataField="PackageTestSystemID"

        DataType="System.Int64"

        HeaderText="ID" SortExpression="PackageTestSystemID"

        UniqueName="PackageTestSystemID" AllowFiltering="false">

    </telerik:GridBoundColumn>

    <telerik:GridTemplateColumn HeaderText="Package" UniqueName="Package"

        SortExpression="PackageVersion.PackageName" AllowFiltering="true">

      <ItemTemplate>

         <asp:Label id="PackageLabel" runat="server"

         Text='<%# Eval("PackageVersion.PackageName") %>'>

       </asp:Label>

      </ItemTemplate>

   </telerik:GridTemplateColumn>

    <telerik:GridTemplateColumn HeaderText="Revision" UniqueName="Revision"

        SortExpression="PackageVersion.Revision" AllowFiltering="false">

      <ItemTemplate>

         <asp:Label id="RevisionLabel" runat="server"

         Text='<%# Eval("PackageVersion.Revision") %>'>

       </asp:Label>

      </ItemTemplate>

   </telerik:GridTemplateColumn>

    <telerik:GridTemplateColumn HeaderText="Tester" UniqueName="Tester"

        SortExpression="TestSystem.TestSystemSerial" AllowFiltering="false">

      <ItemTemplate>

         <asp:Label id="TesterLabel" runat="server"

             Text='<%# Eval("TestSystem.TestSystemSerial") %>'>

       </asp:Label>

      </ItemTemplate>

   </telerik:GridTemplateColumn>

</Columns>

This is done in Telerik’s RadGrid control. For those who are working with the standard gridview, it’s a snap too. Scott Guthrie shows how- Scott’s blog

The catch is, I got all of this to work with the LinqDataSource, TestPackageLDS, shown below-

 

<asp:LinqDataSource ID="TestPackagesLDS" runat="server"

      ContextTypeName="EM.Facility.DAL.FacilityEMDataContext"

      TableName="PackageTestSystems"

      EnableDelete="True" EnableInsert="True" EnableUpdate="True">

</asp:LinqDataSource>

 

Which produces the Grid-

However, I didn’t start that way. Since I was going to just display this information. I initially had my TestPackageLDS with insert, update, delete  Not enabled. Without these enabled, I’m guessing the TestPackageLDS decided to not get them and you see the following grid and get to wonder… where’d it all go.


 

Enabling just one of the update, insert, delete options and voila, problem fixed. I have not attempted this with the Gridview, but I suspect the issue lies in the LinqDataSource and the results will be the same. The LinqDataSource (and SqlDataSource) are useful tools for prototyping and simple applications. You could say they let you cheat, and you know cheaters never prosper. In this case, they just had me work a little bit to pay my dues. Have fun, I hope this helps.

John.

Blogging? Blogging?

OK, this is my first tiny step into the online unknown. I don't know where I'm going to find the time for this. I don't know who is going to track me down, stalk me, flame me. We'll see... going awry.

john.