Archive | October, 2007

Installing .Net 2.0 Framework on existing v1.1 servers

31 Oct

This post relates to the situation where some .Net applications have been converted to v2.0 but not all of them, so there is a mixture of v1.1 and v2.0 apps on the same server. There are some really good articles and blog posts on this subject already that have been immensely helpful, see here. But nothing beats having to tackle these problems for yourself!

So, I’m working for a client at the moment that has a mixture of classic ASP, COM+, Windows services, console apps an ASP.Net web sites and services, most of which are written in .Net v1.1, VB 6 and C++. We have written a new application in v2.0 of .Net and what to test out the effects of applying the .Net 2.0 framework to the server.

The key area of investigation is around evaluating what will happen when v2.0 of the framework is placed on these servers. If the answer is “nothing, all should be fine” then read on!

This mode of operation is side-by-side frameworks and avoids DLL hell to a large degree. What will be confusing to most people is the scenarios under which the latest version of the CLR is loaded despite some .Net apps being compiled under v1.1 of the CLR.

There seems to be a number of factors that affect the version of the CLR loaded into the appropriate process:-

  • The version the app was compiled against that is held in the manifest
  • For web-apps, the version on the ASP.NET tab
  • The available versions on the target machine, e.g v1.1 app installed on machine with v2.0 only
  • Any overrides specified in the config file (supportedruntime and requiredruntime elements) 
  • The nature of the client calling the .Net application (managed or unmanaged code).

Unmanaged Client

We have found that when an unmanaged client calls a .Net v1.1 application (that doesn’t have any .Net configuration file in the client folder area), the c:\windows\system32 directory is probed and the latest version of mscoree.dll is loaded. This is not suprising when you learn that v2.0 of the framework updates the mscoree.dll in this directory when it is installed onto the server.

Due to breaking changes between v1.1 and v2.0 of .Net here I would recommend that older versions of .Net apps run on the version of the framework that they were written for until such time that they can be upgraded and tested thoroughly. To this end, a simple fix to the above problem is to install a config file of the form:-

<unmanaged_application_name>.exe.config   (e.g. testapp.exe.config)

into the folder where the client application is running from, that contains the following entries:-

<?xml version =”1.0″?>
<configuration>
    <startup>
        <supportedRuntime version=”v1.1.4322″/>
        <requiredRuntime version=”v1.1.4322″/>
    </startup>
</configuration>

Classic ASP pages calling .Net DLL’s directly from the page

So, the latest version of the framework loading into the IIS worker process relates to a .Net object or .Net DLL being referenced directly from a classic ASP page which uses COM interop (but not COM+). This will cause the IIS process to load the latest version of the .Net CLR and the .Net referenced DLL will run inside the IIS worker process with this version, which may cause problems depending on exactly what the .Net object/DLL does. If it uses parts of the CLR code where a breaking change has occurred between 1.1 and 2.0 there will be a problem.

If for instance the classic ASP page were referencing a .net DLL, by GACing the DLL and placing inside COM+ and running the DLL as a separate “server” process ensures that it will run inside the surrogate DLLHOST.exe having its own IDENTITY and process. Then the correct version of the framework CLR will be loaded into the surrogate process based on available versions and the requirements of the DLL within its manifest, e.g. if compiled as v1.1 with available CLR versions of v1.1 and v2.0, the process would have the v1.1 CLR loaded into the COM+ process.

If the classic ASP page is referencing a series of .Net objects directly from the page then Scott gives a solid solution here.

We used NTFileMon.exe from SYSINTERNALS (now managed by Microsoft) to establish the probing and eventual CLR version being loaded and used.

Code Access Security

It is worth being mindful of the fact that if you find yourself in the above mentioned position with the latest version of the CLR loading against your wishes, you will also then be forcd onto the latest version of Code Access Security (CAS). If you decide to keep the latest version of the CLR loading, ensure that your v1.1 CAS settings are also reflected in CAS v2.0.

For a thorough discussion of all of the above topics see here

Model-View-Presenter (MVP) in VB ASP.Net

29 Oct

Introduction

After spending quite a bit of time being sucked into the whole Code Behind mess of ASP.Net, I am finally getting some use out of the MVP pattern. There will have been plenty written about what it is, that it is a UI pattern and its many benefits, suffice to say that is what we should be aiming for when designing user, business and data layer components behind a user interface, be it ASP.Net, WinForms, Mobile, etc. Why? Because we are trying to achieve some important tenets of good design that being loose coupling with high cohesion. Cohesion is about robust, reliable, understandable and reusable designs/applications whilst loose coupling is about communicating through a stable interface. Another huge benefit to using this pattern for interface programming is that it allows you write tests that mock the various interface implementations to allow isolated unit testing.

Side Note:

I do have some reservations for using this pattern, particularly as I do a fair bit of work with datagridview controls(WinForms) or DataGrid (ASP.Net) as the intention of the pattern is to use the “View” to represent the data items relating to the user interface which is far more complicated when dealing with collections of datarows. Also, the handling of events and different code paths through the UI code behind make this pattern more cumbersome to implement and use. But more on that in a part 2 posting.

The alternative to MVP seen in many solutions is to use the code behind to assemble serialisable domain classes or xml documents and pass these between UI and user process code ensuring that the user process layer, business and data layer make no reference whatsoever to the original UI presentation data items such as text and combo boxes. This is often also achieved with the use of web services between the layers.

The View

The View shows a representation of the model and is usually distinguished by a stable interface e.g:-

Public Interface IView
   Property FullName() As String
   Property DateOfBirth() As String
   Property ErrorMessage() As String
End Interface

The Model

The Model is responsible for execution of business rules and storage of the data and again is usually distinguished by a stable interface e.g:-

Public Interface IModel
   Function StoreDetails(ByVal dets As IView) As String
   Function GetDetailsByID(ByVal idx As Integer) As ArrayList
   Function GetDetailsByName(ByVal name As String) As ArrayList
End Interface

The model will be supported by the associated concrete implementation. This example is of course highly contrived but the pattern underneath is the key principle here:-

Public Class Model
    Implements IModel

Public Function GetDetailsByID(ByVal idx As Integer) As System.Collections.ArrayList
  Implements Model.GetDetailsByID
       'Code to retrieve form details
       Dim res As ArrayList = New ArrayList(New String() {"simon", "Peter", "Jane"})
       Return res
  End Function

Public Function GetDetailsByName(ByVal name As String) As System.Collections.ArrayList
    Implements IModel.GetDetailsByName
      'Code to retrieve form details
      Dim res As ArrayList = New ArrayList(New String() {"Peter", "Jane"})
      Return res
  End Function

Public Function StoreDetails(ByVal dets As IView) As String Implements IModel.StoreDetails
      'Code to store form details
      '...
      Return String.Format("Stored details for {0} : {1}", dets.FullName, _
                                                      Format(CDate(dets.DateOfBirth), "yyyy/MM/dd"))
  End Function
End Class

The Presenter

The Presenters job is to present the view to the model and in so doing communcate between these layers:-

Public Class Presenter
   Dim thisView As IView
   Dim busLayer As IModel = New Model

   Public Sub New(ByVal view As IView)
      If view Is Nothing Then
         Throw New ArgumentException("view cannot be nothing")
      Else
         thisView = view
      End If
   End Sub

Function ValidateDOB() As Boolean
      Return IsDate(thisView.DateOfBirth)
End Function

Function StoreDetails() As String
      Return busLayer.StoreDetails(thisView)
   End Function
End Class

The Code behind file

Finally, the code behind ASP.Net page (could easily be some other UI client type) must implement the view’s interface and store the specifics of the UI controls values in the view and invoke the presenter to mediate between the UI and the model layers using the View data:-

Partial Class _Default
   Inherits System.Web.UI.Page
   Implements IView

   Dim thisView As IView  

Public Property DateOfBirth() As String Implements IView.DateOfBirth
      Get
         Return Me.TxtDOB.Text
      End Get
      Set(ByVal value As String)
         Me.TxtDOB.Text = value
      End Set
   End Property

Public Property FullName() As String Implements IView.FullName
      Get
         Return Me.TxtFullName.Text
      End Get
      Set(ByVal value As String)
         Me.TxtFullName.Text = value
      End Set
   End Property
Public Property ErrorMessage() As String Implements IView.ErrorMessage
      Get
         Return Me.LblResult.Text
      End Get
      Set(ByVal value As String)
         Me.LblResult.Text = value
      End Set
   End Property

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles BtnSubmit.Click
      Try
         Dim pres As Presenter = New Presenter(Me)
         Me.LblResult.Text = pres.StoreDetails()
      Catch ex As Exception
         Me.LblResult.Text = ex.Message
      End Try
   End Sub
End Class

Conclusion

So, a fairly simple example to start with. The complications to this pattern will arise from the use of gridviews and data containers with many rows as well as how to handle page transitions, session data and page workflow and it may be that other patterns are required to fully implement a neat solution.

In the seond part to this article I will attempt to address these issues.

Here we go…

29 Oct

OK, after thinking about blogging for a while now, finally with the clocks going back one hour this Sunday 28th October 2007 creating enough free time, I plan to use the extra hour to set up a blog and make my first post.

The intention of the blog will be to record findings in my work that are of interest to me and perhaps to others. Those sorts of solutions to problems where, after many hours of deliberation you find an answer to a problem that you are satisfied with and need to record the outcome somewhere that is indexable and searchable – hence this blog.

Like most I trawl all over Google looking for answers to different problems and occasionally find the answers in a podcast or book. To my mind there is quite alot of white noise on the Internet at present, much to confuse the unwary and desperate and it is my aim to record my findings based on what has been tried and tested and that basically work for me.

This blog will have a heavy Microsoft .Net bias since that’s what I work with and will cover design and programming issues, patterns and practices, testing, documentation, etc. Any code samples will be in VB.Net as that is my preferred syntax. I will do a post on why I think I am being asked to standardise on C# in the near future.

So read on – hope this blog helps you demystify the noise!

Follow

Get every new post delivered to your Inbox.