Contents tagged with Extensibility

  • Making Better Use of the NHibernate HiLo Generator


    NHibernate’s HiLo (High-Low) id generation algorithm is one of the most commonly used, and for good reasons:

    • It is database-independent, that is, does not rely on any database-specific functionality such as SQL Server’s IDENTITY and Oracle’s SEQUENCE;
    • It allows batching of inserts;
    • It complies with the Unit of Work pattern, because it sends all writes at the same time (when the session is flushed);
    • Your code does not need to know or care about it.

    Now, this post does not intent to explain this algorithm in depth, for that I recommend the NHibernate HiLo Identity Generator article or Choosing a Primary Key: Natural or Surrogate?, for a more in-depth discussion of id generation strategies. Here I will talk about how to make better use of the NHibernate implementation.

    Max Low

    First of all, you can configure the max low value for the algorithm, using by code mapping, like this:

       1: x.Generator(Generators.HighLow, g => g.Params(new { max_lo = 100 }));

    The default max low value is 32767. When choosing a lower or a higher value, you should take into consideration:

    • The next high value is updated whenever a new session factory is created, or the current low reaches the max low value;
    • If you have a big number of inserts, it might pay off to have a higher max low, because NHibernate won’t have to go to the database when the current range is exhausted;
    • If the session factory is frequently restarted, a lower value will prevent gaps.

    There is no magical number, you will need to find the one that best suits your needs.

    One Value for All Entities

    With the default configuration of HiLo, a single table, row and column will be used to store the next high value for all entities using HiLo. The by code configuration is as follows:

       1: this.Id(x => x.SomeId, x =>
       2: {
       3:     x.Column("some_id");
       4:     x.Generator(Generators.HighLow);
       5: });

    The default table is called HIBERNATE_UNIQUE_KEY, and its schema is very simple:


    Whenever NHibernate wants to obtain and increment the current next high value, it will issue SQL like this (for SQL Server):

       1: -- select current value
       2: select next_hi
       3: from hibernate_unique_key with (updlock, rowlock)
       5: -- update current value
       6: update hibernate_unique_key
       7: set next_hi = @p0
       8: where next_hi = @p1;

    There are pros and cons to this default approach:

    • Each record will have a different id, there will never be two entities with the same id;
    • Because of the sharing between all entities, the ids will grow much faster;
    • When used simultaneously by several applications, there will be some contention on the table, because it is being locked whenever the next high value is obtained and incremented;
    • The HIBERNATE_UNIQUE_KEY table is managed automatically by NHibernate (created, dropped and populated).

    One Row Per Entity

    Another option to consider, which is supported by NHibernate’s HiLo generator, consists of having each entity storing its next high value in a different row. You achieve this by supplying a where parameter to the generator:

       1: this.Id(x => x.SomeId, x =>
       2: {
       3:     x.Column("some_id");
       4:     x.Generator(Generators.HighLow, g => g.Params(new { where = "entity_type = 'some_entity'" }));
       5: });

    In it, you would specify a restriction on an additional column. The problem is, NHibernate knows nothing about this other column, so it won’t create it.

    One way to go around this is by using an auxiliary database object (maybe a topic for another post). This is a standard NHibernate functionality that allows registering SQL to be executed when the database schema is created, updated or dropped. Using mapping by code, it is applied like this:

       1: private static IAuxiliaryDatabaseObject OneHiLoRowPerEntityScript(Configuration cfg, String columnName, String columnValue)
       2: {
       3:     var dialect = Activator.CreateInstance(Type.GetType(cfg.GetProperty(NHibernate.Cfg.Environment.Dialect))) as Dialect;
       4:     var script = new StringBuilder();
       6:     script.AppendFormat("ALTER TABLE {0} {1} {2} {3} NULL;\n{4}\nINSERT INTO {0} ({5}, {2}) VALUES (1, '{6}');\n{4}\n", TableHiLoGenerator.DefaultTableName, dialect.AddColumnString, columnName, dialect.GetTypeName(SqlTypeFactory.GetAnsiString(100)), (dialect.SupportsSqlBatches == true ? "GO" : String.Empty), TableHiLoGenerator.DefaultColumnName, columnValue);
       8:     return (new SimpleAuxiliaryDatabaseObject(script.ToString(), null));
       9: }
      11: Configuration cfg = ...;
      12: cfg.AddAuxiliaryDatabaseObject(OneHiLoRowPerEntityScript(cfg, "entity_type", "some_entity"));

    Keep in mind that this needs to go before the session factory is built. Basically, we are creating a SQL ALTER TABLE followed by an INSERT statement that change the default HiLo table and add another column that will serve as the discriminator. For making it cross-database, I used the registered Dialect class.

    Its schema will then look like this:


    When NHibernate needs the next high value, this is what it does:

       1: -- select current value
       2: select next_hi
       3: from hibernate_unique_key with (updlock, rowlock)
       4: where entity_type = 'some_entity'
       6: -- update current value
       7: update hibernate_unique_key
       8: set next_hi = @p0
       9: where next_hi = @p1
      10: and entity_type = 'some_entity';

    This approach only has advantages:

    • The HiLo table is still managed by NHibernate;
    • You have different id generators per entity (of course, you can still combine multiple entities under the same where clause), which will make them grow more slowly;
    • No contention occurs, because each entity is using its own record on the HIBERNATE_UNIQUE_KEY table.

    One Column Per Entity

    Yet another option is to have each entity using its own column for storing the high value. For that, we need to use the column parameter:

       1: this.Id(x => x.SomeId, x =>
       2: {
       3:     x.Column("some_id");
       4:     x.Generator(Generators.HighLow, g => g.Params(new { column = "some_column_id" }));
       5: });

    Like in the previous option, NHibernate does not know and therefore does not create this new column automatically. For that, we resort to another auxiliary database object:

       1: private static IAuxiliaryDatabaseObject OneHiLoColumnPerEntityScript(Configuration cfg, String columnName)
       2: {
       3:     var dialect = Activator.CreateInstance(Type.GetType(cfg.GetProperty(NHibernate.Cfg.Environment.Dialect))) as Dialect;
       4:     var script = new StringBuilder();
       6:     script.AppendFormat("ALTER TABLE {0} {1} {2} {3} NULL;\n{4}\nUPDATE {0} SET {2} = 1;\n{4}\n", TableHiLoGenerator.DefaultTableName, dialect.AddColumnString, columnName, dialect.GetTypeName(SqlTypeFactory.Int32), (dialect.SupportsSqlBatches == true ? "GO" : String.Empty));
       8:     return (new SimpleAuxiliaryDatabaseObject(script.ToString(), null));
       9: }
      11: Configuration cfg = ...;
      12: cfg.AddAuxiliaryDatabaseObject(OneHiLoColumnPerEntityScript(cfg, "some_column_id"));

    The schema, with an additional column, would look like this:


    And NHibernate executes this SQL for getting/updating the next high value:

       1: -- select current value
       2: select some_column_hi
       3: from hibernate_unique_key with (updlock, rowlock)
       5: -- update current value
       6: update hibernate_unique_key
       7: set some_column_hi = @p0
       8: where some_column_hi = @p1;

    The only advantage in this model is to have separate ids per entity, contention on the HiLo table will still occur.

    One Table Per Entity

    The final option to consider is having a separate table per entity (or group of entities). For that, we use the table parameter:

       1: this.Id(x => x.SomeId, x =>
       2: {
       3:     x.Column("some_id");
       4:     x.Generator(Generators.HighLow, g => g.Params(new { table = "some_entity_unique_key" }));
       5: });

    In this case, NHibernate generates the new HiLo table for us, together with the default HIBERNATE_UNIQUE_KEY, if any entity uses it, with exactly the same schema:


    And the SQL is, of course, also identical, except for the table name:

       1: -- select current value
       2: select next_hi
       3: from some_entity_unique_key with (updlock, rowlock)
       5: -- update current value
       6: update some_entity_unique_key
       7: set next_hi = @p0
       8: where next_hi = @p1;

    Again, all pros and no cons:

    • Table still fully managed by NHibernate;
    • Different ids per entity or group of entities means they will grow slower;
    • Contention will only occur if more than one entity uses the same HiLo table.


    As you can see, NHibernate is full of extensibility points. Even when it does not offer out of the box what we need, we usually have a way around it.

    Let me hear from you!


  • NHibernate Connection Resiliency

    Entity Framework 6 included a feature known as connection resiliency. Basically, what it says is, when EF is trying to connect to a database, it will try a number of times before giving up. After each unsuccessful attempt, it will wait some time and then try again. As you can imagine, this is very useful, especially when we are dealing with cloud storage.

    NHibernate does not natively offer this, however, because it is highly extensible, it isn’t too hard to build one such mechanism, which is what I did.

    The code is below, as you can see, it consists of a custom implementation of DriverConnectionProvider, the component of NHibernate that opens connections for us.

       1: public class ResilientDriverConnectionProvider : DriverConnectionProvider
       2: {
       3:     public const String ConnectionDelayBetweenTries = "connection.delay_between_tries";
       4:     public const String ConnectionMaxTries = "connection.max_tries";
       6:     private static readonly IInternalLogger log = LoggerProvider.LoggerFor(typeof(ResilientDriverConnectionProvider));
       8:     public ResilientDriverConnectionProvider()
       9:     {
      10:         this.MaxTries = 3;
      11:         this.DelayBetweenTries = TimeSpan.FromSeconds(5);
      12:     }
      14:     public Int32 MaxTries { get; set; }
      16:     public TimeSpan DelayBetweenTries { get; set; }
      18:     public override void Configure(IDictionary<String, String> settings)
      19:     {
      20:         String maxTries;
      21:         String delayBetweenTries;
      23:         if (settings.TryGetValue(ConnectionMaxTries, out maxTries) == true)
      24:         {
      25:             this.MaxTries = Int32.Parse(maxTries);
      26:         }
      28:         if (settings.TryGetValue(ConnectionDelayBetweenTries, out delayBetweenTries) == true)
      29:         {
      30:             this.DelayBetweenTries = TimeSpan.Parse(delayBetweenTries);
      31:         }
      33:         base.Configure(settings);
      34:     }
      36:     public override IDbConnection GetConnection()
      37:     {
      38:         IDbConnection con = null;
      40:         for (var i = 0; i < this.MaxTries; ++i)
      41:         {
      42:             try
      43:             {
      44:                 log.Debug(String.Format("Attempting to get connection, {0} of {1}", (i + 1), this.MaxTries));
      45:                 con = base.GetConnection();
      46:                 log.Debug(String.Format("Got a connection after {0} tries", (i + 1)));
      48:                 break;
      49:             }
      50:             catch(Exception ex)
      51:             {
      52:                 if (i == this.MaxTries - 1)
      53:                 {
      54:                     log.Error(String.Format("Could not get connection after {0} tries", this.MaxTries), ex);
      55:                     throw;
      56:                 }
      57:                 else
      58:                 {
      59:                     Thread.Sleep(this.DelayBetweenTries);
      60:                 }
      61:             }
      62:         }
      64:         return (con);
      65:     }
      66: }

    The code wraps the attempt to open a connection and retries it a number of times, with some delay in between.

    The way to configure this, in fluent configuration, would be:

       1: var cfg = new Configuration()
       2:     .DataBaseIntegration(
       3:     db =>
       4:     {
       5:         db.ConnectionProvider<ResilientDriverConnectionProvider>();
       6:         //...
       7:     });

    Or if you prefer to use string properties, in either XML or fluent configuration, you can do:

       1: var cfg = new Configuration()
       2:     .SetProperty(NHibernate.Cfg.Environment.ConnectionProvider, typeof(ResilientDriverConnectionProvider).AssemblyQualifiedName);

    From looking at the class, you can see that it supports two properties:

    • MaxTries: the maximum number of connect attempts;
    • DelayBetweenTries: the amount of time to wait between two connection attempts.

    It is possible to supply this values by configuration:

       1: var cfg = new Configuration()
       2:     .SetProperty(NHibernate.Cfg.Environment.ConnectionProvider, typeof(ResilientDriverConnectionProvider).AssemblyQualifiedName)
       3:     .SetProperties(ResilientDriverConnectionProvider.ConnectionMaxTries, "3")
       4:     .SetProperties(ResilientDriverConnectionProvider.ConnectionDelayBetweenTries, TimeSpan.FromSeconds(5).ToString());

    As usual, hope you find this useful! Smile


  • Delete By Id in NHibernate

    NHibernate allows executable queries, that is, plain old UPDATEs, INSERTs and DELETEs. This is great, for example, for deleting an entity by its id without actually loading it. Note, that the following won’t give you that:

       1: session.Delete(session.Load<TEntity>(id));

    NHibernate will load the proxy before it actually deletes it. But the following does work perfectly:

       1: public static Boolean DeleteById(this ISession session, Type entityType, Object id)
       2: {
       3:     var metadata = session.SessionFactory.GetClassMetadata(entityType);
       5:     var hql = String.Format("delete {0} where id = :id", metadata.EntityName);
       7:     var results = session.CreateQuery(hql).SetParameter("id", id).ExecuteUpdate();
       9:     return (results == 1);
      10: }
      12: public static Boolean DeleteById<T>(this ISession session, Object id)
      13: {
      14:     return (DeleteById(session, typeof(T), id));
      15: }

    A single DELETE SQL command is sent to the database with this approach.


  • ASP.NET Web Forms Extensibility: Handlers

    In the .NET world, all HTTP requests, whether they be for web services (XML, WCF, Web API), pages (Web Forms and MVC), etc, are processed by a handler. Basically, a handler is a particular implementation of the IHttpHandler interface, and requests are routed to a particular handler class by one of four ways:

    • An entry on the Web.config file, on the httpHandlers section;
    • An instance returned from a Handler Factory;
    • A route handler, like in MVC or Dynamic Data;
    • Explicitly requested by the URL, in the case of ASHX generic handlers.

    The httpHandlers section can specify both a handler or a handler factory for a specific URL pattern (say, for example, /images/*.png), which may be slightly confusing. I have already discussed handler factories in another post, have a look at it if you haven’t already. A simple registration would be:

       1: <httpHandlers>
       2:     <add verb="*" path="Image.axd" type="MyNamespace.MyHandler, MyAssembly"/>
       3: </httpHandlers>

    Another option is through a route. The IRouteHandler interface defines a method GetHttpHandler which returns the route handler that will handle the request. You can register a IRouteHandler instance for a specific route by setting the RouteHandler property inside the Route class.

    Finally, there’s another kind of handler that doesn’t need registering and that is called explicitly: generic handlers. These are .ASHX markup files without any user interface elements that merely reference a code-behind class, which must implement IHttpHandler (you can also place code in the .ASHX file, inside a <script runat=”server”> declaration). Here’s an example:

       1: <%@ WebHandler Language="C#" Class="Handler" %>
       2: <script runat="server" language="C#">
       2: public class Handler : System.Web.IHttpHandler
       3: {
       4:     //...
       5: }

    Having said that, what is a handler good for? The IHttpHandler interface only defines one method, ProcessRequest, and a property, IsReusable. As you can tell, this is considerably more simple than, for example, the Page class, with its myriad of virtual methods and events, which, of course, is also an implementation of IHttpHandler. Because of that, it is much more useful for handling requests that do not need a complex lifecycle. Some scenarios:

    • Downloading a file;
    • Uploading a file;
    • Streaming;
    • Redirecting;
    • Returning values for consumption by JavaScript, in AJAX style;
    • Tracing and monitoring, like ELMAH or the Trace handler;
    • Generating content dynamically, such as images.

    The IsReusable indicates to the ASP.NET infrastructure if the hander’s instance can be reused for different identical requests or if a new instance needs to be created. If you don’t store state on the handler’s class, it is safe to return true.

    As for the ProcessRequest method, a simple implementation might be:

       1: public class ImageHandler : IHttpHandler
       2: {
       3:     public void ProcessRequest(HttpContext context)
       4:     {
       5:         Bitmap bmp = new Bitmap(400, 300);
       7:         Graphics g = Graphics.FromImage(bmp);
       8:         g.DrawRectangle(new Pen(new SolidBrush(Color.Green)), 10, 10, 300, 200);
       9:         g.DrawString(context.Request.Url.Query, new Font("Arial", 30), new SolidBrush(Color.Yellow), new PointF(10f, 10f));
      11:         context.Response.ContentType = "image/gif";
      13:         bmp.Save(context.Response.OutputStream, ImageFormat.Gif);
      14:     }
      16:     public Boolean IsReusable
      17:     {
      18:         get
      19:         {
      20:             return (true);
      21:         }
      22:     }
      23: }

    This will create an image with a text string that is obtained from the query string, that is, anything in the URL after the ? symbol.

    Don’t forget to always return the appropriate content type, because the browser won’t know how to handle the content you send without it.

    One final note: from an handler you normally don't have access to the session - the Session property is null. If you need to use it, you must declare that your handler implements IRequiresSessionState or IReadOnlySessionState, the later for read-only access. That's basically what ASP.NET does when, on your page's markup, you place a EnableSessionState attribute.


  • ASP.NET Web Forms Extensibility: URL Mapping

    A long time before ASP.NET Routing came along, ASP.NET already offered a similar functionality: it was called URL mapping.

    URL mapping allows having virtual URLs that redirect to real ones. For example, you can have all requests for “/Product/IPhone” redirected to “/Product.aspx?ID=10”. This allows two simple things:

    • Hiding complexity (the ID parameter, for example);
    • Hiding the technology in use (in this case, the .ASPX extension is never seen);
    • Redirecting from one page (such as Default.aspx) to another transparently.

    You can configure URL mapping by just adding entries to the urlMapping section on Web.config:

       1: <urlMappings enabled="true">
       2:     <add url="~/Product/IPhone" mappedUrl="~/Product.aspx?ID=10"/>
       3: </urlMappings>

    And that’s it, no modules or additional configuration.

    You can keep using the QueryString collection:

       1: Int32 id = Convert.ToInt32(this.Request.QueryString["ID"]);     //10
       2: String path = this.Request.Path;                                //Product.aspx

    The Url property also contains the real URL, but the RawUrl contains the requested URL:

       1: String requestedPath = this.Request.RawUrl;    //Product/IPhone
       2: String mappedPath = this.Request.Url;          //http://localhost/Product.aspx?ID=1

    So, as you can see, this is much simpler that ASP.NET Routing and should only be used in very simple scenarios: when you are using a version of ASP.NET prior to 3.5, or you want to configure routes only through the Web.config file.


  • ASP.NET Web Forms Extensibility: Tag Mapping

    There may be times when you want a particular setting applied to all controls of a given type, in all pages. Or you want to debug this control, but you don’t have access to it’s source code. Or you want to change its behavior. For that, you can use tag mapping, and I have given an example before.

    In a nutshell, ASP.NET lets you change the control that would normally be instantiated by some server tag (like <asp:Image />, <asp:TextBox />, etc) for your own control, which must inherit from the class of the original control. This means that on all places that you have declared, for example, an <asp:TextBox />, instead of the standard TextBox, ASP.NET will instead place an instance of your own class, where you can override methods, set property defaults on its constructor or place breakpoints.

    Usage is very simple, just add entries to the tagMapping section:

       1: <tagMapping>
       2:     <add tagType="System.Web.UI.WebControls.TextBox" mappedTagType="MyNamespace.MyTextBox, MyAssembly"/>
       3: </tagMapping>

    Remember, MyTextBox must inherit from TextBox, or you will get an exception.

    All of the properties that are present on markup will be passed to the new control, skins will also apply. In case you are wondering, this won’t work with web user controls (those that have an .ASCX file).


  • ASP.NET Web Forms Extensibility: Modules

    Next in the series is modules. So, what is a module, and what does it do?

    A module is some class that implements IHttpModule. This is a very simple interface, which only defines two methods:

    • Init: this is the “body” of the module, where you place it’s logic (more on this later), called when the application is started (typically, upon the first request, unless you are doing application initialization);
    • Dispose: called when the application shuts down.

    A module is typically statically registered on the Web.config file, although I have talked in the past on how to register modules dynamically. While a module usually does not actually do anything by itself, it is useful for registering event handlers for ASP.NET application lifetime events, such as Error, BeginRequest, EndRequest and their likes. Please note that there is no event for the Start occurrence (normally handled on the custom Global class on an Application_Start method), you can just use the Init method for that, since it is called upon application startup.

    Out of the box ASP.NET includes a number of modules, which you can find on the global Web.config file, located in %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\Config, some of which you are free to disable, that is, remove on you local Web.config file:

       1: <!-- for IIS < 7 -->
       2: <httpModules>
       3:    <remove name="PassportAuthentication" />
       4: </httpModules>
       5: <!-- for IIS 7+ -->
       6: <system.webServer>
       7:   <modules>
       8:     <remove name="PassportAuthentication" />
       9:   </modules>
      10: </system.webServer>

    As you can see from the above snippet, one such module is PassportAuthentication, implemented by PassportAuthenticationModule, one that is marked as deprecated in current versions of .NET. Now, there are two sections where modules can be registered, one for IIS versions prior to 7, and the other for recent versions. Of course, if you only use one of them, do forget about the other section.

    A simple module implementation would be:

       1: public class FooterModule : IHttpModule
       2: {
       3:     void IHttpModule.Init(HttpApplication context)
       4:     {
       5:         context.EndRequest += (sender, e)
       6:         {
       7:             HttpContext.Current.Response.Write(String.Format("<p>Generated at {0}</p>", DateTime.UtcNow));
       8:         };
       9:     }
      11:     void IHttpModule.Dispose()
      12:     {
      13:     }
      14: }

    This module registers an event handler for the EndRequest event, which, when called, outputs a string to the response. Nothing to be done on disposing, in this case, but a typical use case would be to release any sort of “heavy” module-held resources when the application shuts down. Please be careful to perform operations only when you can, for example, session is only available after the AcquireRequestState event is raised (and, of course, only for handlers implementing IRequiresSessionState), caller identity is only set after the AuthenticateRequest and authorization is only confirmed after AuthorizeRequest.

    You should favor writing code that handles an event in a module as opposed to having a similar method on Global.asax.cs because a module is more portable – you can even reuse it between different assemblies.

    Once you are finished, you need to register your module on Web.config, to have it being set up automatically. You have to give it a unique name and add an entry like the following:

       1: <!-- for IIS < 7 -->
       2: <system.web>
       3:     <httpModules>
       4:         <add name="MyModule" type="MyNamespace.MyModule, MyAssembly"/>
       5:     </httpModules>
       6: </system.web>
       7: <!-- for IIS 7+ -->
       8: <system.webServer>
       9:     <modules runAllManagedModulesForAllRequests="true">
      10:         <add name="MyModule" type="MyNamespace.MyModule, MyAssembly"/>
      11:     </modules>
      12: </system.webServer>

    Next, handlers and routes! Winking smile


  • ASP.NET Web Forms Extensibility: Expression Builders

    I have talked extensively about expression builders in the past, and that is because I find them extremely useful, for building no code solutions.

    In a nutshell, it is a design-time mechanism for executing a method which receives some parameters and returns something that will be bound to a control’s property. Anyone who has used resources – <%$ Expression:xxx %> -, bound a connection string or an application setting to a data source control – <%$ ConnectionStrings:xxx %> and <%$ AppSettings:xxx %> – on an ASP.NET page has used expression builders. These expression builders are included with ASP.NET, and do useful things, such as returning a connection string or an application setting from the configuration file, or returning a translated resource according to the current browser culture, without the need to code.

    One example would be, for example, picking up some value from the current HttpContext and assigning it to some control’s property. Here’s a simple way to achieve it, using DataBinder.Eval to process possibly complex expressions:

       1: public class ContextExpressionBuilder : ExpressionBuilder
       2: {
       3:     #region Public static methods
       4:     public static Object GetValue(String expression, Type propertyType)
       5:     {
       6:         HttpContext context = HttpContext.Current;
       7:         Object expressionValue = DataBinder.Eval(context, expression.Trim().Replace('\'', '"'));
       9:         expressionValue = Convert(expressionValue, propertyType);
      11:         return (expressionValue);
      12:     }
      14:     #endregion
      16:     #region Public override methods
      17:     public override Object EvaluateExpression(Object target, BoundPropertyEntry entry, Object parsedData, ExpressionBuilderContext context)
      18:     {
      19:         return (GetValue(entry.Expression, entry.PropertyInfo.PropertyType));
      20:     }
      21:     #endregion
      23:     #region Protected static methods
      24:     protected static Object Convert(Object value, Type propertyType)
      25:     {
      26:         if (value != null)
      27:         {
      28:             if (propertyType.IsAssignableFrom(value.GetType()) == false)
      29:             {
      30:                 if (propertyType.IsEnum == true)
      31:                 {
      32:                     value = Enum.Parse(propertyType, value.ToString(), true);
      33:                 }
      34:                 else if (propertyType == typeof(String))
      35:                 {
      36:                     value = value.ToString();
      37:                 }
      38:                 else if ((typeof(IConvertible).IsAssignableFrom(propertyType) == true) && (typeof(IConvertible).IsAssignableFrom(value.GetType()) == true))
      39:                 {
      40:                     value = System.Convert.ChangeType(value, propertyType);
      41:                 }
      42:             }
      43:         }
      45:         return (value);
      46:     }
      47:     #endregion
      49:     #region Public override methods
      50:     public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, Object parsedData, ExpressionBuilderContext context)
      51:     {            
      52:         if (String.IsNullOrEmpty(entry.Expression) == true)
      53:         {
      54:             return (new CodePrimitiveExpression(String.Empty));
      55:         }
      56:         else
      57:         {
      58:             return (new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(new CodeTypeReferenceExpression(this.GetType()), "GetValue"), new CodePrimitiveExpression(entry.Expression.Trim()), new CodeTypeOfExpression(entry.PropertyInfo.PropertyType)));
      59:         }
      60:     }
      61:     #endregion
      63:     #region Public override properties
      64:     public override Boolean SupportsEvaluate
      65:     {
      66:         get
      67:         {
      68:             return (true);
      69:         }
      70:     }
      71:     #endregion
      72: }

    As you can see, there are two methods that may be called in order to retrieve a value:

    In this example, I have implemented both methods, so that it can be used in various scenarios. On the GetCodeExpression method I simply return a Code DOM expression that calls the static method GetValue on my expression builder. I have a method that tries to convert the returned value into the target property on the declaring control, in case they are of different types.

    Expression builders need to be registered on the Web.config file, on the expressionBuilders section:

       1: <configuration>
       2:     <system.web>
       3:         <compilation>
       4:             <expressionBuilders>
       5:                 <add expressionPrefix="Context" type="MyNamespace.ContextExpressionBuilder, MyAssembly"/>
       6:             </expressionBuilders>
       7:         </compilation>

    Finally, here’s how to use this sample expression builder to feed a Label text on a markup file:

       1: <span>Value of cookie MyId: <asp:Label runat="server" Text="<%$ Context:Request.Cookies['MyId'].Value %>" /></span>

    This is identical to having the following code:

       1: myLiteral.Text = HttpContext.Current.Request.Cookies["MyId"].Value;

    The syntax is <%$ MyRegisteredPrefix: SomeString %>, where MyRegisteredPrefix is what you want it to be, and what is registered on Web.config, and SomeString is also a randomly-formed string. Note that the expression builders forbid us to using in this string, so, what I did was allow to be used instead, and replace them at runtime.

    What remains to be said is regarding editors for allowing integrated expression builder design inside Visual Studio, but since that is strictly not required, I leave it to some other time.

    As usual, hope you find this of use. Look for the other expression builders that I wrote, all code is available on the blog.