.NET and me Coding dreams since 1998!

29Nov/070

Enterprise Web Applications using Web Client Software Factory | Altairis – kalendář akcí

On December 13th, my colleagues from Monster and me are having together a session regarding Web Client Software Factory, but this time instead of Microsoft building it would be hosted in Monster offices located in heart of Prague downtown.

The session would be again orientated to some practical "real world" advices and I hope it would be fun as the previous ones were. Come join us!

 Register here: Enterprise Web Applications using Web Application Software Factory | Altairis - kalendář akcí

Map image
Filed under: Uncategorized No Comments
14Nov/072

How to access server side variable from client side code on UX friendly way

Armen blogged about the best way how to make java script in code behind, which made me blogging this post.

I really think that the java script doesn't belong to code behind and that in most of the typical use cases can be easily ported to client side

The reasons behind that mine opinion are:

  • It is hard to maintain and update java script made by concatenating strings in code behind
  • Every single change (no matter how small requires rebuilding) which can take 15-20 minutes in some applications
  • UX persons (experts for Java Script kung fu) in general prefer staying in markup level and hate going in code behind
  • DEV persons in general prefer UX staying outside of code behind :)

So an example of typical use case I am seeing on code reviews, is building a java script in code behind because the code need to embed into the script control run time ClientID (in case you don't know what is it take a peak here)

The code I am describing is covering next use case:

There are text box and a button controls on a web form and page defines an integer property called TestProperty.
Click on the button should produce a client side alert message which would show the entered content of the text box and a value of the test property

So the markup looks something like this

   1: <form id="form1" runat="server">
   2: <div>
   3:      <asp:TextBox ID="InputTextBox" runat="server" />
   4:      <input type="button" value="Alert" onclick="Print();" />
   5: </div>
   6: </form>

The string builder code behind approach to implementing use case (and I am pretty sure you've seen it yourself a lot of times)  could look like this:

   1: private int _testProperty;
   2: public int TestProperty
   3: {
   4:     get { return _testProperty; }
   5:     set{_testProperty = value;}
   6: }
   7:  
   8: protected void Page_Load(object sender, EventArgs e)
   9: {
  10:     TestProperty = 3;
  11:     StringBuilder sb = new StringBuilder();
  12:     sb.AppendLine(@"<script type='text/javascript'>");
  13:     sb.AppendLine(@"function Print()");
  14:     sb.AppendLine(@"{");
  15:     sb.AppendFormat(@"alert(document.getElementById('{0}').value);n", InputTextBox.ClientID);
  16:     sb.AppendFormat(@"alert(Test value='{0});n", TestProperty);
  17:     sb.AppendLine(@"}");
  18:     sb.AppendLine(@"</script");
  19:     if (!Page.ClientScript.IsClientScriptBlockRegistered("print"))
  20:         Page.ClientScript.RegisterClientScriptBlock(GetType(), "print", sb.ToString());
  21: }

In lines 1-6 we have a plain old integer property definition which value we set in first line (line 10) of the Page_Load method. 

So, in lines 11-18 code is concatenating the text of the java script function with a special cases happening in:

  • line 15 where we concatenate to java script string ClientID property value of the InputTextBox server side control
  • line 15 where we concatenate to java script string value of the TestProperty

In line 19 then we check if we didn't register the script already and in case not (in line 20) we are registering it.
(I'll live this piece of code in this state fully aware of how unoptimized it is:) )

Obviously, the reason why the server side java script is been used here is the need for accessing some server side property from client side. This java script needs a server side control attribute value and a server side variable value.

The way how to do the same thing on client side is based on very simple idea: usage of good old <%=  something  %> tag which allows (in place of something) referring any server side, code behind variable

So the same functionality implemented on markup (client side) level would look like this:

   1: <form id="form1" runat="server">
   2: <div>
   3:      <asp:TextBox ID="InputTextBox" runat="server" />
   4:      <input type="button" value="Alert" onclick="Print();" />
   5: </div>
   6:  
   7: <script type="text/javascript">
   1:  
   2:     function Print()
   3:     {
   4:      alert(document.getElementById('<%= InputTextBox.ClientID %>').value);
   5:      alert(<%= TestProperty %>);
   6:     }

7: </script>

   8:  
   9: </form>

Notice that:

  •  in line 4, I am using <%= InputTextBox.ClientID %> which means something like "Insert here ClientID value of the server side control InputTextBox"
  • in line 5, I am using <%= TestProperty %> which means something like "Reach out to server side and give me the value of TextProperty variable

With this approach no code in page load is required, Print function can be modified on client side only without the need of rebuilding the web application and making changes in code such is changing property name breaks the build

That contributes a lot to increasing productivity and happiness of UX people :)

Conclusion

Having in mind how natural it is building java script on client side but still "aware of server side" I really think that usage of JavaScriptStringBuilder should be discouraged and used only in use cases when the same thing can not be done on the way described (if there any cases like that in real world)

 

Share this post :

Filed under: Uncategorized 2 Comments
12Nov/0711

How to build your own SQL Server Explorer

Recently, I've started making in my free time my own little ORM tool, mainly as an fun way into exploration of the ADO .NET 2.0

Every  dissent ORM tool has to be based on DB object enumeration activities and I've noticed there are not a lot straight "how to" articles on net how to do various things (at least I had a hard time finding them), so I decided to make a simple blog post describing exactly those How-To's

How to enumerate visible SQL server instances

Enumerating visible instances of MS SQL Server can be performed by executing the GetDataSource() of the SqlDataSourceEnumerator type singleton instance.

GetDataSource returns four column data table with next columns:

  1. ServerName - Name of the server.
  2. InstanceName - Name of the server instance. Blank if the server is running as the default instance.
  3. IsClustered - Indicates whether the server is part of a cluster.
  4. Version - Version of the server (8.00.x for SQL Server 2000, and 9.00.x for SQL Server 2005).

Code example:

   1: public static IList<string> GetActiveServers()
   2: {
   3:     Collection<string> result = new Collection<string>();
   4:     SqlDataSourceEnumerator instanceEnumerator = SqlDataSourceEnumerator.Instance;
   5:     DataTable instancesTable = instanceEnumerator.GetDataSources();
   6:     foreach (DataRow row in instancesTable.Rows)
   7:     {
   8:         if (!string.IsNullOrEmpty(row["InstanceName"].ToString()))
   9:             result.Add(string.Format(@"{0}{1}", row["ServerName"], row["InstanceName"]));
  10:         else
  11:             result.Add(row["ServerName"].ToString());
  12:     }
  13:     return result;
  14: }

How to enumerate databases of the given SQL server instance

Enumerating the databases of the given server can be performed by executing the GetSchema method of the SqlConnection instance with a SqlClientMetaDataCollectionNames.Databases string enumeration value passed to method.

Passing that enumeration or it's string equivalent ("Databases") is totally the same, except enumeration looks cooler :)

Code example:

   1: public static IList<string> GetDatabases(string serverName, string userId, string password,
   2:                                               bool windowsAuthentication)
   3:      {
   4:          Collection<string> result = new Collection<string>();
   5:          using (
   6:              SqlConnection connection =
   7:                  GetActiveConnection(serverName, string.Empty, userId, password, windowsAuthentication))
   8:          {
   9:              connection.Open();
  10:              DataTable dt = connection.GetSchema(SqlClientMetaDataCollectionNames.Databases);
  11:              foreach (DataRow row in dt.Rows)
  12:              {
  13:                  result.Add(string.Format("{0}", row[0]));
  14:              }
  15:          }
  16:          return result;
  17:      }

In line 6, we are using an instance of SqlConnection type created by GetActiveConnection method.

In line 10, we are calling GetSchema connection instance method which returns a data table with a single column which contains the name of the database

in ADO NET, methods used for retrieving schema information always are overloaded with a version accepting additional string array parameter which is used for passing the restrictions (you can think of it as a filter criteria) which ADO.NET should apply while retrieving resulting set.
Retrieving database schema in our example has only one restriction and that is database name so if we would write something like

   DataTable dt = connection.GetSchema("Databases", new string[] {"Northwind" });

Please notice in that that line that I used "Databases" and not enumeration and that I have passed single string array with "Nortwind" content.
Result of passing that restriction would be that ADO NET would retrieve only databases fulfilling the restriction requirement, which means only Nortwind database data would be returned

GetActiveConnection method creates a new SqlConnection instance using SqlConnectionStringBuilder class which is used to build connection string for given parameters.

Something like this

   1: private static SqlConnection GetActiveConnection(string serverName, string databaseName, string userName,
   2:                                                  string password, bool useIntegratedSecurity)
   3: {
   4:     SqlConnectionStringBuilder connBuilder = new SqlConnectionStringBuilder();
   5:     connBuilder.DataSource = serverName;
   6:     connBuilder.InitialCatalog = databaseName;
   7:     connBuilder.IntegratedSecurity = useIntegratedSecurity;
   8:     connBuilder.UserID = userName;
   9:     connBuilder.Password = password;
  10:     return new SqlConnection(connBuilder.ConnectionString);
  11: }

I'll be using this helper methods also in rest of the examples

How to enumerate tables of the given database

In general, the procedure of retrieval tables is the same as the procedure described for databases, in a sense that the GetSchema method of SqlConnection instance is been called but this time with SqlClientMetaDataCollectionNames.Tables ("Tables") enumerated value.

The big difference between those two is in the fact that tables restriction are contained of four different constraint arguments:

  1. database name
  2. owner/schema name ("dbo")
  3. table name (which should contain null value if we want to retrieve all tables of database)
  4. table type (which can have values "VIEW" for views and "BASE TABLE" for tables

So, to retrieve the list of tables for a given database we could use code similar to the next one:

   1: public static IList<string> GetTables(string serverName, string databaseName, string userId, string password,
   2:                                       bool windowsAuthentication)
   3: {
   4:     string[] restrictions = new string[4];
   5:     restrictions[0] = databaseName; // database/catalog name   
   6:     restrictions[1] = "dbo"; // owner/schema name   
   7:     restrictions[2] = null; // table name   
   8:     restrictions[3] = "BASE TABLE"; // table type    
   9:     Collection<string> result = new Collection<string>();
  10:     using (
  11:         SqlConnection connection =
  12:             GetActiveConnection(serverName, databaseName, userId, password, windowsAuthentication))
  13:     {
  14:         connection.Open();
  15:         DataTable dt = connection.GetSchema(SqlClientMetaDataCollectionNames.Tables, restrictions);
  16:         foreach (DataRow row in dt.Rows)
  17:         {
  18:             if (!row[2].ToString().StartsWith("sys"))
  19:                 result.Add(string.Format(@"{0}", row[2]));
  20:         }
  21:     }
  22:     return result;
  23: }
Column keys of the columns of the data table returned are:
  • Column 0. "table_catalog"
  • Column 1. "table_schema"
  • Column 2. "table_name"
  • Column 3. "table_type"

How to enumerate columns of the given table

The list of restriction parameters for column retrieval is shorter and it contains next 3 string values:

  1. Database name
  2. Owner/schema name
  3. Table name

SqlConnection instance GetSchema method gets this time SqlClientMetaDataCollectionNames.Columns ("Columns") enumerated value and the resulting data table contains next 18 columns:

Column 0 - "TABLE_CATALOG"
Column 1 - "TABLE_SCHEMA"
Column 2 - "TABLE_NAME"
Column 3 - "COLUMN_NAME"
Column 4 - "ORDINAL_POSTION"
Column 5 - "COLUMN_DEFAULT"
Column 6 - "IS_NULLABLE"
Column 7 - "DATA_TYPE"
Column 8 - "CHARACTER_MAXIMUM_LENGTH"
Column 9 - "CHARACTER_OCTET_LENGTH"
Column 10 - "NUMERIC_PRECISION"
Column 11 - "NUMERIC_PRECISION_RADIX"
Column 12 - "NUMERIC_SCALE"
Column 13 - "DATETIME_PRECISION"
Column 14 - "CHARACTER_SET_CATALOG"
Column 15 - "CHARACTER_SET_SCHEMA"
Column 16 - "CHARACTER_SET_NAME"
Column 17 - "COLLATION_CATALOG"

I believe column names are self explanatory and familiar to all of us, so I'll skip explanation of what they stand for

In our little example we would return concatenated string containing the column name and data type, where data type in case of char data types would show maximal number  of characters and in case of decimal precision data.

The code doing that might look like this:

   1: public static IList<string> GetColumns(
   2:        string serverName, string databaseName, string userId,
   3:        string password, bool windowsAuthentication, string tableName)
   4:    {
   5:        SqlConnection connection =
   6:            GetActiveConnection(serverName, databaseName, userId, 
   7:                                password, windowsAuthentication);
   8:  
   9:        string[] restrictions = new string[3];
  10:        restrictions[0] = connection.Database; // database/catalog name      
  11:        restrictions[1] = "dbo"; // owner/schema name      
  12:        restrictions[2] = tableName; // table name      
  13:        IList<string> result = new Collection<string>();
  14:        using (connection)
  15:        {
  16:            connection.Open();
  17:            DataTable columns = connection.GetSchema(SqlClientMetaDataCollectionNames.Columns, restrictions);
  18:            foreach (DataRow row in columns.Rows)
  19:            {
  20:                string columnName = row[3].ToString();
  21:                string columnDataType = row[7].ToString();
  22:                if (columnDataType.IndexOf("char") > -1)
  23:                {
  24:                    // row[8] - CHARACTER_MAXIMUM_LENGTH    
  25:                    columnDataType = string.Format("{0}({1})", columnDataType, row[8]);
  26:                }
  27:                if (columnDataType.IndexOf("decimal") > -1)
  28:                {
  29:                    // row[10] - CHARACTER_OCTET_LENGTH    
  30:                    // row[11] - NUMERIC_PRECISION    
  31:                    columnDataType = string.Format("{0}({1},{2})", columnDataType, row[10], row[11]);
  32:                }
  33:                result.Add(string.Format("{0},{1}", columnName, columnDataType));
  34:            }
  35:            return result;
  36:        }
  37:    }

How to enumerate indexes of the table

List of restrictions which can be used for indexes is the same as the one used for table, with 4 elements: database name, schema, table name and table type

We are executing GetSchema method of SqlConnection instance with SqlClientMetaDataCollectionNames.IndexColumns ("IndexColumns") enumerated value sent as a parameter and the resulting data table contains next 9 columns

  • Column 0 - "constraint_catalog"
  • Column 1 - "constraint_schema"
  • Column 2 - "constraint_name"
  • Column 3 - "table_catalog"
  • Column 4 - "table_schema"
  • Column 5 - "table_name"
  • Column 6 - "column_name"
  • Column 7 - "ordinal_position"
  • Column 8 - "KeyType"
  • Column 8 - "index_name"

Column 8 ("KeyType") describes the data type of the index and contains a numeric value which points to certain data type.

There's a list:

34 :  image
35 :  text
48 :  tinyint
52 :  smallint
56 :  int
58 :  smalldatetime
59 :  real
60 :  money
61 :  datetime
62 :  float
98 :  sql_variant
99 :  ntext
104 :  bit
106 :  decimal
108 :  numeric
122 :  smallmoney
127 : bigint
165 :  varbinary
167 :  varchar
173 :  binary
175 :  char
189 :  timestamp
231 :  nvarchar
239 :  nchar

So to enumerate indexes, one might write next code:

   1: public static IList<string> GetIndexes(SqlConnection connection, string tableName)
   2:       {
   3:           string[] restrictions = new string[3];
   4:           restrictions[0] = connection.Database; // database/catalog name      
   5:           restrictions[1] = "dbo"; // owner/schema name      
   6:           restrictions[2] = tableName; // table name      
   7:           IList<string> result = new Collection<string>();
   8:           using (connection)
   9:           {
  10:               connection.Open();
  11:               DataTable columns = connection.GetSchema(SqlClientMetaDataCollectionNames.IndexColumns, restrictions);
  12:               foreach (DataRow row in columns.Rows)
  13:               {
  14:                   string columnName = row["column_name"].ToString();
  15:                   string indexName = row["index_name"].ToString();
  16:                   bool isPrimaryKey = row["constarint_name"].ToString().StartsWith("PK");
  17:                   result.Add(string.Format("Index:{0}, on column:{1}, PK:{2}", indexName, columnName, isPrimaryKey));
  18:               }
  19:               return result;
  20:           }
  21:       }

How to enumerate parameters of the stored procedure

Enumeration of parameters used in a stored procedure is been done through usage of the SqlCommandBuilder static DeriveParameters method which accepts the SqlCommand instance constructed for a given sql connection and ctored procedure

According to http://www.codeproject.com/useritems/DetermineSql2005SPParams.asp, there is a difference in how SQL 2000 and SQL 2005 and there's a need of handling that problem with some additional approach, but according to my personal experience that's not the case - I never had problems he described.
So, IMHO to enumerate parameters of a stored procedure next simple code should be used regardless of the SQL version:

   1: public static SqlParameter[] DiscoverStoredProcedureParameters(SqlConnection sqlConnection,
   2:                                                                string storedProcedureName)
   3: {
   4:     SqlCommand cmd = new SqlCommand(storedProcedureName, sqlConnection);
   5:     cmd.CommandType = CommandType.StoredProcedure;
   6:     using (sqlConnection)
   7:     {
   8:         sqlConnection.Open();
   9:         SqlCommandBuilder.DeriveParameters(cmd);
  10:     }
  11:     SqlParameter[] discoveredParameters = new SqlParameter[cmd.Parameters.Count];
  12:     cmd.Parameters.CopyTo(discoveredParameters, 0);
  13:     return discoveredParameters;
  14: }

Test drive

Bellow you can find a source code of a small example which enumerates the databases (on left), tables of selected database (top right) and columns selected table (right down).

image[5]

 

Conclusion

ADO NET 2.0 removes the need of using ADOX or SQLDMO components for the tasks covering examining the structure of the database objects. It is almost trivial (with a bit reading of documentation) to do the thing which were before not-so trivial. But...
Although already very simple to use, I would like to see in future ADO NET 3.0 version  next enhancements:

  • Replacing the property bags as a way of passing arguments with DTOs as data carriers instead of string arrays. I guess that would have to be done in some new SQL connection related helper class to preserve compatibilty
  • For the same reasons I don't like property bags as a method parameter data carriers, I don't like the result data tables
    Having LINQ in place, I don't see the reason why we won't replace the returning DataTables with some more OOP friendly solution

You can download source code of this example here

Share this post :

del.icio.us Tags: ,,
Filed under: Uncategorized 11 Comments
12Nov/070

How to have configuration file for DLL

In cases when I need to make some component independently pluggable, I am defining separate configuration file for that component. That is particular useful if you are not the end user of the component, so you can not rely that appropriate configuration sections would be add to the app.config or web.config file.


Today's use case would be covering the need for defining a collection of user data stored in a component configuration file and that data should be read during the read time and returned as a collection of concatenated strings. Every user entry would have unique Id and first name but not necessarily the last name entry,


Project structure


image


Configuration file definition


Would look like something like this:



   1: <?xml version="1.0" encoding="utf-8"  standalone="yes" ?>
   2: <configuration>
   3:   <configSections>
   4:     <sectionGroup name="SomeSectionGroupName" >
   5:       <section name="AuthenticationSection" type="Pluggin.AuthenticationConfigurationSection, Pluggin" />
   6:     </sectionGroup>
   7:   </configSections>
   8:   <SomeSectionGroupName>
   9:     <AuthenticationSection>
  10:       <UserCollection>
  11:         <UserConfigurationElement id="1" name="Nikola" surname="Malovic" />
  12:         <UserConfigurationElement id="2" name="Snezana" surname="Malovic" />
  13:         <UserConfigurationElement id="3" name="Nina" />
  14:       </UserCollection>
  15:     </AuthenticationSection>
  16:   </SomeSectionGroupName>
  17: </configuration>

Configuration file would contain:



  • (L4) Configuration section group called "SomeSectionGroupName" and in that section group
  • (L5) Configuration section named: "AuthenticationSection"
  • (L10) AuthenticationSection would contain configuration ellement collection "UserCollection"
  • (L11, L12,L13) which would group collection of "UserConfigurationElement"

ConfigurationSection definition


As we can see in line 5 of configuration file, AuthenticationSection is defined by type AuthenticationConfigurationSection located in Pluggin assembly.


The code defined there is very simple and it is based on specialization of the base ConfigurationSection with defining the mappings between the config file xml entities and appropriate CLR types


Code is very simple and it looks like this:



   1: using System.Configuration;
   2:  
   3: namespace Pluggin
   4: {
   5:     public class AuthenticationConfigurationSection : ConfigurationSection
   6:     {
   7:  
   8:         [ConfigurationProperty("UserCollection", IsDefaultCollection = true)]
   9:         public UserConfigurationElementCollection Users
  10:         {
  11:             get { return (UserConfigurationElementCollection)base["UserCollection"]; }
  12:         }
  13:  
  14:     }
  15: }

In line 8, we are using ConfigurationProperty attribute to define that "this specific config file section would contain a "UserCollection" XML collection element"


In line 11, we define mapping between that element and UserConfigurationElementCollection type and that is all this configuration section


ConfigurationElementCollection definition


The configuration element collection implementation is based on inheriting the ConfigurationElementCollection and implementing base abstract methods CreateNewElement() and GetElementKey(ConfigurationElement element)


Code looks something like this:



   1: using System.Configuration;
   2:  
   3: namespace Pluggin
   4: {
   5:     public class UserConfigurationElementCollection : ConfigurationElementCollection
   6:     {
   7:  
   8:         protected override ConfigurationElement CreateNewElement()
   9:         {
  10:             return new UserConfigurationElement();
  11:         }
  12:  
  13:         protected override object GetElementKey(ConfigurationElement element)
  14:         {
  15:             return ((UserConfigurationElement)element).Id;
  16:         }
  17:  
  18:         public override ConfigurationElementCollectionType CollectionType
  19:         {
  20:             get { return ConfigurationElementCollectionType.BasicMap; }
  21:         }
  22:  
  23:         protected override string ElementName
  24:         {
  25:             get { return "UserConfigurationElement"; }
  26:         }
  27:     }
  28: }

In line 8, we override the abstract creation member and set it up to return new instance of UserConfigurationElement (which is our specialized configuration element - I will cover it in more detail in a few seconds)


In line 13, we override the get element key method to cast the given element to UserConfigurationElement and return its Id property (which is key attribute)


To enable mapping the configuration element XML definition  and the CLR configuration element definition we need to add additional overrides in L18 and L23 which enable .NET to find during run time appropriate configuration element type which is to be mapped to certain config element.
Without those two additional overrides, my little sample would throw  an ConfigurationErrorsException:



A first chance exception of type 'System.Configuration.ConfigurationErrorsException' occurred in System.Configuration.dll


Additional information: Unrecognized element 'UserConfigurationElement'.


ConfigurationElement definition


In L11,L12 and L13 we can see that configuration of this element has three properties Id, Name, surname (except in L13 where surname is missing)


Mapping of this configuration definition to .NET type is been done by inheriting the ConfigurationElement class and defining mapping between the configuration element properties and appropriate class properties with optional defining of additional ttributes


That code could look like this:



   1: using System.Configuration;
   2:  
   3: namespace Pluggin
   4: {
   5:     public class UserConfigurationElement : ConfigurationElement
   6:     {
   7:         [ConfigurationProperty("id", IsKey = true, IsRequired = true)]
   8:         public string Id
   9:         {
  10:             get { return (string)this["id"]; }
  11:             set { this["id"] = value; }
  12:         }
  13:  
  14:         [ConfigurationProperty("name", IsRequired = true)]
  15:         public string FirstName
  16:         {
  17:             get { return (string)this["name"]; }
  18:             set { this["name"] = value; }
  19:         }
  20:  
  21:         [ConfigurationProperty("surname", IsRequired = false)]
  22:         public string LastName
  23:         {
  24:             get { return (string)this["surname"]; }
  25:             set { this["surname"] = value; }
  26:         }
  27:     }
  28: }

In line 5, we can see that our UserConfigurationElement inherits the ConfigurationElement


In line 7, we are decorating property Id with configuration property attribute who defines that:



  • the Id property is to be mapped to the "id" (case sensitive) XML element property
  • that the id element property contains unique identifier data of the configuration element
  • that the id element value is required data so it can not be omitted

In line 14, we have the same configuration property attribute decoration but this time we can an example of totally different naming of the .NET property, so we don't have to follow chosen XML names if we don't want because attribute constructor element name value defines  the mapping


In line 21, we see the same configuration property attribute decoration but with IsRequired = false value definition which in this case mean that some of the elements could be without surname value


Run-time configuration file content read out


Now when we have configuration file defined and appropriate types defining mapping XML->NET all we have to do is to use them during the run time.


The code loading the authentication section from a given config file looks like this:



   1: private static AuthenticationConfigurationSection GetAuthenticationConfigurationSection()
   2: {
   3:     ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
   4:     Assembly asm = Assembly.GetCallingAssembly();
   5:     Uri uri = new Uri(Path.GetDirectoryName(asm.CodeBase));
   6:     fileMap.ExeConfigFilename = Path.Combine(uri.LocalPath, "pluggin.dll.config");
   7:     Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
   8:  
   9:     AuthenticationConfigurationSection authConfigurationSection =
  10:         config.GetSectionGroup("SomeSectionGroupName").Sections["AuthenticationSection"] as
  11:         AuthenticationConfigurationSection;
  12:     if (authConfigurationSection == null)
  13:         throw new NotSupportedException();
  14:  
  15:     return authConfigurationSection;
  16: }

In determine local path of the configuration file we used:



  • in line 4, we got a pointer to the active assembly
  • In line 5, we used GetDirectoryName static method of the Path type for  active assembly code base propety value.
    Then we passed retrieved directory name to the Uri object constructor
  • In line 6, we set the ExeConfigFilename property of the fileMap instance (created in line 3), to a string concatenated from uri.LocalPath and hard coded config file name value (This could be enhanced to be dynamically determined to be like asembly.dll.config)
  • That file map instance is then passed as a parameter to OpenMappedExeConfiguration method of the COnfigurationManager type

The code is using the local path of the Uri object constructed based upon active assembly directory name to set the ExeConfigFile name property of the ExeConfigurationFileMap type instance. That  instance is then passed as parameter to ConfigurationManager OpenMapperdExeConfiguration method


In Line 9 and 10, we  retrieve from opened configuration file  section group with SomeSectionGroupName and AuthenticationSection section which we cast then to AuthenticationConfigurationSection


L12, just checks if something went wrong


Now when we have strongly typed reference to configuration section, it's read out is fairly trivial task:



   1: public static IEnumerable<string> GetUsers()
   2: {
   3:     AuthenticationConfigurationSection builderSection = GetAuthenticationConfigurationSection();
   4:     foreach (UserConfigurationElement userConfigurationElement in builderSection.Users)
   5:     {
   6:         yield return
   7:             String.Format("id:{0}, name:{1}, surname:{2}", userConfigurationElement.Id,
   8:                           userConfigurationElement.FirstName, userConfigurationElement.LastName);
   9:     }
  10: }

In line 3, we call previously explained method which returns an instance of AuthenticationConfigurationSection pointing to appropriate configuration file section


In line 3 we iterate through all Users (property defined in AuthenticationConfigurationSection which maps "UserCollection" XML element to UserConfigurationElement collection.


In line 6-8, for each UserConfigurationElement we access its properties Id, FirstName and LastName (which are mapped to appropriate xml configuration element properties), and return the string containing concatenated property values.


Test drive


To test the functionality, I've created simple console application with next code:



   1: using System;
   2: using System.Collections.Generic;
   3: using System.Text;
   4: using Pluggin;
   5:  
   6: namespace TestDrive
   7: {
   8:     class Program
   9:     {
  10:         static void Main(string[] args)
  11:         {
  12:             IEnumerable users =Builder.GetUsers();
  13:             foreach (string user in users)
  14:             {
  15:                 Console.WriteLine(user);
  16:             }
  17:             Console.ReadKey();
  18:         }
  19:     }
  20: }

which once started results with:


image


Conclusion


It is possible and in fact it is very simple to define an "application  independent" component configuration file which could allow encapsulating the required default component setting up from the end component user while still allowing configuration level customization


You can download source code from here.


 




 
























Share this post :

Filed under: Uncategorized No Comments
4Nov/0719

Model View Presenter (MVP) design pattern close look – Part 2 – Passive View

What is Model View Presenter?

MVP pattern is one of the major patterns used for extracting business logic outside of UI elements and by that, enabling unit testing the UI without the need for using specific UI based testing tools

If you are new to Model View Presenter pattern at all, you should check the Model View Presenter entry level post which explains the most important concepts of wiring the presenter and view in step by step manner. Once you would chew that, come back to this post and continue reading :)

  As we can see from this diagram:

  • View contains the Presenter instance (view "knows" presenter)
  • Presenter is the only class knowing how to reach to model and retrieve the data needed for performing business logic
  • Presenter talks to the View through the view interface (abstracted representation of the View without UI specific attributes)
  • View doesn't know nothing about the Model

View responsibility is to show the data provided by presenter, and purpose of the presenter is to reach to model, retrieve the needed data, performs required processing and returns the UI prepared data to the view.

In July 2006, two year old Model View Presenter pattern has been retired and two variations from original MVP pattern came up:

  1. Supervising controller - where the view is handling UI operations on his own based upon the DTO sent by presenter
  2. Passive screen -  subject of today's post. I've already blogged about it, but that post was more of L100 type of post where I deliberately melt down presenter and model, so the most important thing presenter - view wire up could be more clear. Today's post would dig deeper into the Passive view and give a couple of additional information's with proper implementation model presenter separation of concerns .

Stage set up

Today's example would deliberately use the same use case, model and view markup as the one  used in previous supervising controller blog post to makes easier understanding distinction between the two flavors of the MVP pattern implementation, so check out that post for the details on how the example stage is set up before continuing.

Here, I'll just summary example set up into:

  1. Use case describes a web page which should provide database user search functionality for a given user name. Web page is presenting first name, last name and collection of user addresses. In case no user is found for a given username, error message should be presented. If user updates first name or last name, those changes has to be persisted.
  2. Model is represented with a type implementing the IUserService interface which defines two methods: string GetUser(string userName) and void SaveUser(User user). Retrieving/Saving of user should be done by using

The page in design mode would look something like this:

image  

Passive (screen) view

Passive view is a type of MVP design pattern based on a concept that the view of interface should be abstracted representation of the view, where view UI elements would be represented with .NET plain data types. In that way, presenter is (on decoupled way) aware of view UI elements so he could set/get values directly from the view, without the need of any DTO being used by view as a way of viewer<->presenter communication. .

The biggest advantage of the passive view is that leaves the view with only a "few lines of code" making it so simple that it doesn't require testing different then taking a quick look on the view code. Presenter is now having absolute control on view behavior so testing the presenter is all we have to do to verify even that the view works ok. Another very important advantage is the one David Hayden likes so much, and that is: it enables active work separation between the UX's and DEV's, because DEV can make the complete view page logic without having a page(view) at all. All he has to do is to code against agreed view interface (page approximation). All UX guy has to do is to implement view interface on the view (which is pretty trivial thing to be done) and after that he has all the freedom to work not caring what DEV does.

From what I learned from UX people I met so far, they want to stay away of code behind as much as possible. With supervising controller MVP implementation the question of ownership of actual page/control code behind (aspx.cs/ascx.cs) is unclear and usually ends having both UX/DEV working on it. With passive view, UX owns aspx and aspx.cs and DEV owns presenter and model. Amen! :)

The disadvantage of empowering the presenter is that it can lead to very complex presenter classes with a lot of things to be tested where some of them ay not be related strictly to business logic.

Anyhow, IMHO passive view extreme testability provides much greater gain than it causes pain with having more complex presenters. When we add to that equation ability of effective team multitasking  enabling

View interface

View interface in passive view flavor of MVP is usually having much more members defined (comparing with supervising controller) because each one of the interface members  represents abstraction of a view UI element. That allow

That's how:

  • labels are represented with string setter-only properties,
  • text boxes with getter/setter strings, 
  • repeaters, data lists, data grids  etc are represented with collections of strings or other plain types
  • check boxes are represented with boolean values
  • option buttons with integer/string (containing the pointer to the selected one)
  • drop down lists/lists  - Dictionary<TKey, TValue>

image

Interface contains next abstract representations:

  • Collection of strings representing a collection of user addresses. (setter only -> read only)
  • First name and last name strings - (getter and setter)
    There is requirement that user should be able to update those two so the presenter cares about the changes 
  • Search criteria - (getter only)
    Presenter is not setting the value of the search criteria text box. It just reads the value user typed in.
  • ShowResultPannel setter only boolean property  which enables presenter to perform explicit action on view (hide/show the result panel)
  • Label showing error messages is abstracted to StatusMessage  (setter only -> read only)  

There are no events in the view interface

There is no event definition as an abstraction of the search button click event, because view would in button click event handler just directly call the public presenter method which should occur when a button click happens.

The downside of that approach is that now view is coupled to ("view knows") the presenter which in theory is not a best practice, but in real world I could see it only causing problems if you plan to use different presenters with the same view. In my personal experience and in general reading the MVP related stuff on the web, I couldn't find anyone speaking about that use case as something from the real world, so I am not therefore concerning this as a viable architecture concern.

What we gain from this approach is that we have now much simpler view-presenter wire up code where there is no need for event publishing in view nor for event subscribing code in presenter. Testability is increased to because it is much simpler to just call public presenter method to trigger that behavior then to trigger it indirectly through simulation of the event occurrence. Take a look   how complex test code for that event evocation could look :)

There are no DTO (data transfer object)

Due to the fact that presenter is indirectly manipulating the view elements and that the view is "dumb", there is no need for using any DTO objects because there is no need for presenter to pass any kind of data to the view, because view doesn't do anything.

View implementation

Presenter wire up

The pattern used for establishing wire up between the view and presenter is dependency injection - constructor type.

The  key concepts of this wire up are:

  • presenter has a constructor accepting parameter of view interface type
  • view implements the view interface
  • view in page load constructs a presenter instance and throw himself to the presenter
  • presenter has a pointer then to the view, but the pointer type is view interface so presenter is not knowing nothing about the UI specific aspects of the view he's been injected
  • view keeps created instance of the pointer in the page field to support presenter method invocation in case of specific UI events

In code that would look like this:

   1: private UserDetailsPresenter _presenter;
   2:  
   3: protected void Page_Load(object sender, EventArgs e)
   4: {
   5:     // injecting the view into the presenter
   6:     _presenter = new UserDetailsPresenter(this);
   7: }

Implementing view interface

The view is a web page implementing the view interface just to perform simple mapping of the view interface members and appropriate view UI elements they represent, something like this:

   1: #region IUserDetailsView Members
   2:  
   3: public IEnumerable<string> Address
   4: {
   5:     set
   6:     {
   7:         AdressesRepeater.DataSource = value;
   8:         AdressesRepeater.DataBind();
   9:     }
  10: }
  11:  
  12: public string FirstName
  13: {
  14:     get { return FirstNameTextBox.Text; }
  15:     set { FirstNameTextBox.Text = value; }
  16: }
  17:  
  18: public string LastName
  19: {
  20:     get { return LastNameTextBox.Text; }
  21:     set { LastNameTextBox.Text = value; }
  22: }
  23:  
  24: public string SearchCriteria
  25: {
  26:     get { return SearchCriteriaTextBox.Text; }
  27: }
  28:  
  29: public bool ShowResultPannel
  30: {
  31:     set { resultPanel.Visible = value; }
  32: }
  33:  
  34: public string StatusMessage
  35: {
  36:     set { ResultLabel.Text = value; }
  37: }
  38: #endregion

In line 7, we see that when presenter .sets the Address property of the view interface that would result with that string collection being used as a data source of a repeater. That's how presenter knows only about the collection string property but indirectly setting it, he works with the UI elements itself without having any knowledge about them.

Properties FirstName and LastName perform wire up of the view interface members to the text property of appropriate textboxes. When presenter set a value for a IUserDetailsView.FirstName he fills the FirstNameTextBox.Text value. When presenter reads the IUserDetailsView.LastName, he reads the LastNameTextBox.Text control property value. All the time, not knowing a thing about text boxes, presenter work with them.

In line 26, Presenter would read the string value of IUserDetailsView.SearchCriteria which would return him the entry user made in SearchCriteriaTextBox control

In line 31, presenter setting the boolean value of IUserDetailsView.ShowResultPannel, hide/show the panel containing the results.

At the end, in line 36, presenter can set the string value of IUserDetailsView.StatusMessage property if he wants to present a error message on the web page

UI specific event handling

As I've previously said, in this example there won't be any event driven code to support view event handling. Instead, view would make a direct call  to presenter, something like this:

   1: protected void OnUserSearchButtonClicked(object sender, EventArgs e)
   2: {
   3:     _presenter.OnUserSearched();
   4: }
   5:  
   6: protected void OnUserSaveButtonClicked(object sender, EventArgs e)
   7: {
   8:     _presenter.OnUserSave();
   9: }

As we can see in line 3 and 5, the view simply calls a presenter method of on a field containing presenter instance and by that simple command, when save button would be clicked, presenter's OnUserSave() method would be called.

Presenter

Class diagram of the presenter looks like this:

image

As we can see from the diagram, presenter has:

  • two public constructors: one accepting the view and service interface and one accepting only the view with poor man dependency injection creation of the default service interface implementation
  • Two public methods containing the logic needed for handling appropriate UI view events.
  • Presenter has also three fields which are holding the presenter pointers to the view and service layers and to  user originally retrieved from service layer

Presenter initialization

All the business logic of controlling,presenting and updating model and interaction with view should be encapsulated in the presenter. In this example Presenter is getting pointer to the view interface and model services through the utilization of constructor type of dependency injection design pattern.

   1: private readonly IUserService _userService;
   2: private readonly IUserDetailsView _view;
   3:  
   4: public UserDetailsPresenter(IUserDetailsView view)
   5:     : this(view, new UserServiceStub())
   6: {
   7: }
   8:  
   9: public UserDetailsPresenter(IUserDetailsView view, IUserService userService)
  10: {
  11:     _view = view;
  12:     _userService = userService;
  13: }

In lines 11 and 12, presenter is storing interface representations of the given view and service. That's how the _view field would be a pointer to a view web page and presenter would working with that field work with a web page not knowing that (I've explained how in view interface implementation section)

Presenter implementing view required logic

We have two methods in presenter which perform certain actions for a view, when view requests them.

We saw that view would in case of button clicked directly call presenter public method which would perform appropriate action

OnUserSave method implementation

   1: public void OnUserSave()
   2: {
   3:     bool isFirstNameChanged = (_originalUser.Name != _view.FirstName);
   4:     bool isLastNameChanged = (_originalUser.Surname != _view.LastName);
   5:     if (isFirstNameChanged || isLastNameChanged)
   6:     {
   7:         _originalUser.Name = _view.FirstName;
   8:         _originalUser.Surname = _view.LastName;
   9:         _userService.SaveUser(_originalUser);
  10:     }
  11: }

In line 3 and 4, we see how presenter checks if the user edited presented user data. Presenter does that by comparing the values of user instance retrieved from a database with appropriate  view interface implementation.

Example: when in line 3 presenter compares originally retrieved user name with _view.FirstName he compares behind the curtain original value with the text of the FirstNameTextBox control because view is implementing the view interface by wiring up view interface members with real controls.

That's how presenter talks with a view through the view interface

OnUserSearch method implementation

   1: public void OnUserSearched()
   2:     {
   3:         _view.ShowResultPanel = false;
   4:         if (string.IsNullOrEmpty(_view.SearchCriteria))
   5:         {
   6:             _view.StatusMessage = "User name can not be null";
   7:             return;
   8:         }
   9:  
  10:         _originalUser = _userService.GetUser(_view.SearchCriteria);
  11:         if (_originalUser == null)
  12:         {
  13:             _view.StatusMessage = String.Format("There's no user found for user name:{0}", _view.SearchCriteria);
  14:             return;
  15:         }
  16:  
  17:         _view.FirstName = _originalUser.Name;
  18:         _view.LastName = _originalUser.Surname;
  19:         _view.Address = MapUserAddress(_originalUser.Addresses);
  20:  
  21:         _view.ShowResultPanel = true;
  22:     }

In line 3, presenter sets a _view.ShowResultPanel=false, which would  result executing of the next page (view) code

public bool ShowResultPannel
{
    set { resultPanel.Visible = value; }
}

which would hide the old search results on the start of the search.

In line 4, presenter checks if user entered any search criteria by accessing text property of the SearchCriteriaTextBox control via view interface SearchCriteria property. In case user didn't enter any search criteria, presenter in line 6 sets a view interface member value which would result with view showing that string on ResultLabel.

In line 10, presenter reaches out to model and retrieves a user for a given search criteria.

In line 11, presenter checks the result of user retrieval and if there are no users retrieved for a given criteria, shows an error message in line 13. 

In lines 17,18,19 presenter sets the view interface members values which result with appropriate UI actions - setting text boxes and repeater data bounding.

At the end, in line 21, presenter shows result panel to the user

Summary

Passive view pattern is a UI design pattern which moves most of the responsibilities from web pages leaving them to do just plain view interface implementation with wiring up interface members with appropriate UI control properties.

That gives all the brains to presenter, which enables TDD approach because presenter is UI technology  agnostic, so we are able to write test methods against it and by testing the presenter we are testing indirectly the page itself.

That and its suitability for decoupled team work makes passive view my favorite  flavor of the MVP/MVC pattern regardless of the downsides  it has

Source code of today's example can be found here:   Passive (screen) view source code

What is next?

Next parts of the MVP saga would try to take a close look on a conceptual differences between the MVC and MVP patterns which would be helpful to know considering all the buzz future Microsoft MVC ASP NET framework gets these days.

I plan to write also about MVP pattern usage in cases of composite pages (pages controlling controls) which would be something very interested because I am fan of controls having their own presenters so it could be quite challengeable on a first encounter handling all this interfaces on a elegant way.

At the end of the MVP post series I would make a detail post about how to test in real world MVP patterns which would be a more advanced and detailed version of the L100 post I wrote already

Quote of the day:
Anything worth doing is worth doing slowly. - Mae West

 

Share this post :

Filed under: Uncategorized 19 Comments