Search code examples
asp.netuser-controls

why displaying-expressions don't work in server/user/custom controls ASP.NET


I know for a fact that we can't use displaying-expressions in server, user nor custom controls; the question is why?

lets take a look at this example:

<div class="test" data-random="<%= TextBoxMode.Password %>">
        <%= TextBoxMode.Password %>
</div>

this outputs:

<div class="test" data-random="2">
        2
</div>

meaning that it EVALUATES the expressions and replace the code-block-tags with the coressponding value, but if we do the exact same thing with, lets say, user control it simply doesn't work:

<uc:LabledInput ID="PasswordLogin_View" Name="Password" InputType="<%= TextBoxMode.Password %>" PlaceHolderText="password..." runat="server" />

Well with the same logic it could simply evaluate the expression and replace the resulting value in the placeholders.

My question is a deep down analysis on why is this happening? Why woudn't it work. The only way to make it work is by using DataBinding:

<uc:LabledInput ID="PasswordLogin_View" Name="Password" InputType="<%# TextBoxMode.Password %>" PlaceHolderText="password..." runat="server" />

and then we have to call DataBind(on the parent or the control itself) somewhere within the page that it is used and in the end let me clarify that this is NOT a dulpicate(similar questions mostly focused on how to get around it and make it work or saying that its simply a Response.Write).


Solution

  • Well, the answer is of course that any and all server side controls INCLUDING your user controls does not allow those expression(s).

    Server side controls are well, are ALREADY server side controls, and ALL of them don't have nor allow such expressions.

    As to why? Probably because you have full use of such controls in code behind, and thus the need for some server expression does not make a whole lot of sense.

    When .net + IIS process that page, it does not feed nor even try to deal with such expressions for such controls.

    However, you CAN kludge this. While these simple text box, or label controls don't allow such expressions?

    They DO allow binding expressions!!!

    In the page, we have this public function:

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    
    End Sub
    
    Public Function MyCompany() As String
    
        ' return current comany name from settings
        Return My.Settings.CompanyName
    
    End Function
    

    And then this markup:

            <h4> <%= MyCompany() %></h4>
            <br />
    
            <asp:TextBox ID="TextBox1" runat="server"                
                Text='<%= MyCompany%>'    >
    
            </asp:TextBox>
    

    When run, we get this:

    enter image description here

    So, asp.net controls simple never did allow such server side expressions.

    But, they DO ALLOW binding expressions!

    So, in place of "=", you can replace with a #.

    So, let's try this:

            <h4> <%# MyCompany() %></h4>
            <br />
    
            <asp:TextBox ID="TextBox1" runat="server"                
                Text='<%# MyCompany%>'    >
    
            </asp:TextBox>
    

    With a "#", then the page will need to fire/trigger databind().

    So, trigger a databind() then, say like this:

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    
        Page.DataBind()
    
    End Sub
    
    Public Function MyCompany() As String
    
        ' return current comany name from settings
        Return My.Settings.CompanyName
    
    End Function
    

    Now, when run, we get this:

    enter image description here

    So, it's not 100% clear why server side expressions were never allowed in standard asp.net controls - but they are not. However, you can swap out the server side expression with a databind() expression, and then you can then use those expressions just about everywhere.

    It is a design and architecture issue. Simple put, any server side control can be setup, changed, and modified by code behind. So, why have two roads, two ways of doing the same thing?

    And you get a lot more control - I find tossing around all those server side expressions intermixed inside of the markup? Messy, hard to change, and not all that great anyway. I suspect that if all the standard asp.net controls allowed this, the world would be suffering in more poverty and confusion for the last 20+ years, and so, I think they made a great decision.

    But, you can using databinding expressions if you want in most cases. You just have to then go:

     me.SomeControl.DataBind()     (vb.net)
    
     this.SomeControl.DataBind();  (c#)
    

    Or, all expressions on the page with this:

     Page.DataBind()
    

    But, be careful - that last one will trigger DataBind() for all controls.

    So, if you have existing gridview, dropdown boxes and trigger a page wide databind?

    Then all of the data bound controls also will re-trigger a databind. In most cases, that means your say gridView will go blank!!

    (unless you add a databind event).

    I mean, in place of the above expressions, or say the kludge databind() idea?

    You could have this markup:

            <h4 id="myHeading" runat="server"></h4>
            <br />
    
            <asp:TextBox ID="TextBox1" runat="server"  >
            </asp:TextBox>
    

    So, we now have free and easy use of the above controls in code behind, and on page load can do this:

    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
    
        myHeading.InnerText = MyCompany()
        TextBox1.Text = MyCompany()
    
    End Sub
    

    And this brings up another issue. Why set a text box to some expression, and then the user can't edit that text box - it will always revert back to the expression?

    But, worse yet?

    MOST server side controls have what we call automatic view state. That means a text box, check box etc?

    They automatic retain the setting or value of the control. So, if you type some text into a text box, and hit a button - on post back, and page return from server? The control STILL keeps it settings. So, having view state for a control, and then ALSO having some server side expression does not make ANY sense, since now two places on the page (control view state) and a server side expression has to be re-run EACH and every time the page renders.

    So, there is a performance issue here also. Server side controls already have a bunch of bits and parts to RETAIN their values, and now we suggesting to introduce expressions that will over-ride the setting in the text box for example.

    So, there are 100s of reasons in favor of not needing nor allowing server side expressions in the markup.

    Last but not least?

    Server side controls DO NOT always render the markup REMOTE CLOSE to what the control is on the page.

    In other words, after the asp.net processor is done with that control, your final output HTML is often VAST different - so much so, that the expression would not make sense.

    Take a simple text box, drop into form, and look at the FINAL rendering. For text box above, we see/find this:

    <input name="TextBox1" type="text" 
       value="The Turtle Creek Company" 
     id="TextBox1">
    

    Note how there is NOT EVEN Text=some expression!!!! - So, how can the system now start to set Text="some" expression when the control render does NOT even have a expression any more!!!

    And let's make the text box multi-line, like this:

            <asp:TextBox ID="TextBox1" runat="server" 
                TextMode="MultiLine" Height="142px" Width="488px" >
            </asp:TextBox>
    

    But, say you wanted to set/change TextMode in above? But, Text mode is due to .net pre processing of that server control into HTML.

    And you now get this when run:

    enter image description here

    But, looking at markup, the Text box is now this:

     <textarea name="TextBox1" rows="2" cols="20" 
        id="TextBox1" style="height:142px;width:488px;">The Turtle Creek Company
     </textarea>
    

    Note how we NOT EVEN using a input HTML type any more!!!!

    In other words, the values, the attributes, the settings for a server side control? When the markup is generated, then we don't even have the SAME attributes that existed before we started!!!

    You think even a simple textbox above is a great example? Now try a GridView, ListView etc. The attributes, the settings? They are not EVEN remote close to the final markup.

    So, those in-line expressions? They ONLY ever make sense for plain Jane markup, since such expressions for server side controls make LITTLE sense, since the markup generated is not EVEN REMOTE close to the markup you placed in the page.

    so, with a server side control, and the markup NOT being standard markup?

    Then how can you have such <%= > expressions then? They don't make sense!!!

    And in your user control? You are MOST free to have + use those <%= > expressions in the CUSTOM markup for that control.

    But, you suggesting that the expressions should work at the markup level in the page. But that server control markup does not really even exist any more. As I show above, that simple text box is NOT REMOTE close to a simple HTML input box, and even just change of textmode causes a VAST different rendering of the control.

    So, in-line expressions? They are for markup - not for server side controls, and they don't make a whole lot of sense for server side controls, since EVEN the attributes of the control like Text may not exist in the final HTML it spits out. How and where do you shove this:

     Text='<%= MyCompany() %>
    

    Where will above go into the final control, when the final control does not even HAVE a Text property any more?

    So server side controls are just that - magic controls who's final actual output has VERY LITTLE relationship to the original markup.

    So, with non-server controls, such expressions make sense, since the markup you type, and the expressions you type are NOT being vast re-processed from that server side control into some complex set of REAL AND VALID markup that is spit out to the page.

    So, with plain Jane markup, then simple substitution of <%= > to some value is easy.

    With a server side control? The attributes in question set to such expressions may well not even exist in the final output.

    So, while you can't use such expressions in the markup that defines the user control?

    You sure as the heck are 100% free to such such expressions in the markup you define for that user control.

    So, if you want to use server expressions in the markup that your custom control generates? You are free to use as such. But the original user control in the markup will be removed, processed to html, and the original settings may well not even exist any more in the final HTML OUTPUT.

    Even the above text box shows this. The simple text box with one tiny change to TextMode=Multiline now does NOT EVEN output a input HTML tag, but now uses a text area - all now with 100% different attributes.