Skapa en ExpressionBuilder för Application-variabler

Hade ett litet problem när jag ville få in en Application-variabel i SelectParameters till en SqlDataSource. Sessions-variabler går ju men ej Application. Se en tutorial för vilka typer av parametrar man kan skicka med som standard.

Googlade runt lite och hittade infomation om något som heter ExpressionBuilder i ramverket som jag aldrig använt tidigare. Med detta kan man skapa egna prefix och koppla det till klasser som tar ut den data man vill åt, och man kan binda värden i kontroller. Så min idé var att skapa en ExpressionBuilder som hämtade ut Application-variabler och det gick väldigt bra.

Här kommer jag gå igenom de steg jag gjorde, det hela handlade om att jag ville åt en egen parameter för vilken @Culture SqlDataSource skulle få som inparameter.

I Global.asx skapar jag parametern baserat på domännamnet. Är det en .se-domän vill jag ha "sv-SE" och för alla andra "en-GB".

protected void Application_BeginRequest(Object sender, EventArgs e)
{
        //Check if domain is swedish
       Application["CurrentCulture"] = HttpContext.Current.Request.Url.ToString().IndexOf("codeodyssey.se") != -1 ? "sv-SE" : "en-GB";
}

Min SqlDataSource ser ut ungefär så här:

<asp:SqlDataSource
    ID="sdsBlogPosts"
    runat="server"
    ConnectionString="<%$ ConnectionStrings:ConnectionString %>"
    SelectCommand="SELECT Title, Message FROM BlogPost WHERE Culture=@Culture"
    DataSourceMode="DataSet">
    <SelectParameters>
        <asp:Parameter Name="Culture" DefaultValue="<%$ AppVar:CurrentCulture%>" />
    </SelectParameters>
</asp:SqlDataSource>

För att få ExpressionBuilder att fungera så deklarerar man den i Web.config.

<compilation debug="false">
  <expressionBuilders>
    <add expressionPrefix="AppVar" type="AppVarExpressionBuilder, __code"/>
  </expressionBuilders>
</compilation>

Och sen själva klassen lägger man i App_Code.

using System.CodeDom;
using System.Web.Compilation;
using System.Web.UI;

/// <summary>
/// Summary description for AppVarExpressionBuilder
/// </summary>

public class AppVarExpressionBuilder : ExpressionBuilder
{
    public override CodeExpression GetCodeExpression(BoundPropertyEntry entry, object parsedData, ExpressionBuilderContext context)
    {
        CodeTypeReferenceExpression targetClass = new CodeTypeReferenceExpression(typeof(AppVarExpressionBuilder));
        const string targetMethod = "GetIdentity";
        CodeExpression methodParameter = new CodePrimitiveExpression(entry.Expression.Trim());
        return new CodeMethodInvokeExpression(targetClass, targetMethod, methodParameter);
    }

    public static object GetIdentity(string param)
    {
        string returnString = string.Empty;
        if (System.Web.HttpContext.Current.Application[param]!=null)
        {
            returnString = System.Web.HttpContext.Current.Application[param].ToString();
        }
        return returnString;
    }
}

Hade stor hjälp av ett artikel av Peter Kellner för att lista ut hur ExpressionBuilders fungerar så tack för den.

Comments

Ta en kik på denna gamla länk om CodeExpressionBuilder på "Infinities Loop" för ytterligare info och sätt att jobba med expression builders. http://weblogs.asp.net/infinitiesloop/archive/2006/08/09/The-CodeExpressionBuilder.aspx
@Jon_w: Tack så mycket för den länken! Kommer ihåg att jag läste den där artikeln för länge sen, men hade helt glömt bort den. Det där är ju riktigt användbart.