Stefan Sedich's Blog

try { Stefan.Code(); } catch(BadCodeException) { NotLikely(); }

  • Different SQL between VB.NET and C# LINQ to SQL SOLVED!!

    Hi All,

    Following my previous post I have solved this issue. Somehow accidently I discovered that if the field has allow nulls set on it VB.NET will add the Where Coalesce in your query hence in my case slowing it down dramatically. It seems that C# does not do this. So finally I have my VB.NET sql comming out exactly the same as in C# simply by turning off allow nulls on my database column... Still seems like odd behaivour to me but for now it all works fine.


    Thanks
    Stefan

  • UserControl OutputCache and VaryByParam not working with postback!!

    Don't know if anyone has come across this before. But if you have a usercontrol that uses VaryByParam and you have it on a page and do a postback you will get the wrong cache item. Use the below test bed to see what I mean, this is following to my post for help on the asp.net forums, I then found this post which showed me it is an issue, following this I think I came up with a solution. That is to add a hidden field to my page with the name MenuID and populate that. Now on postback it seems to work fine, as VaryByParam="MenuID" seems to read the form var MenuID and gets the correct value hence fixing caching.
     

  • Fully Accessible And SEO Friendly Ajax Paging Using DataPager

    Hey All,

    Working on my current project I implemented paging using a listview and a datapager. I then decided it would be much nicer to use AJAX for my paging so wrapped all this up in an updatepanel. Next step was the issue when you would goto a page, select a product and hit the browser back button you would get the first page not the page you were last on. To fix this I simply implemented the ASP.NET AJAX Futures History control which allowed me to save my current page and restore this at a later time.

    Perfect I thought until I started thinking about SEO, now my product catalogue was dead to a search engine as it would only see the first page and not be able to do any further paging. To fix this I went about creating a SEO friendly linkbutton control (I have blogged about this a while back but this is the first time I used it in real life). Basically what the SEO Friendly linkbutton does is render a normal navigateURL and the postback as an onclick. This way with Javascript turned on you get a postback but without you have a normal URL, in my case I am passing the page # in my url like so: http://site.com/catalogue/page-XX/Whatever.aspx, I am using URL Rewriter.NET for my URL rewriting so making a nice URL for this was as simple as adding a new rule into my web.config.

    Firstly here is my custom SEOLinkButton control (Its in VB.NET as is my current project, I have a C# version too but will just post the VB.NET version unless requested):

    Public Class SEOLinkButton
        Inherits LinkButton

    #Region "Properties"

        Public Property NavigateURL() As String
            Get
                Return If(ViewState("NavigateURL") Is Nothing, "", ViewState("NavigateURL").ToString())
            End Get
            Set(ByVal value As String)
                ViewState("NavigateURL") = value
            End Set
        End Property

    #End Region

        Protected Overrides Sub AddAttributesToRender(ByVal writer As System.Web.UI.HtmlTextWriter)

            If (Me.Page IsNot Nothing) Then
                Me.Page.VerifyRenderingInServerForm(Me)
            End If

            Me.EnsureID()
            writer.AddAttribute(HtmlTextWriterAttribute.Id, Me.ClientID)

            If (Not String.IsNullOrEmpty(Me.CssClass)) Then
                writer.AddAttribute(HtmlTextWriterAttribute.Class, Me.CssClass)
            End If

            If (Not Me.Enabled) Then
                writer.AddAttribute(HtmlTextWriterAttribute.Disabled, "disabled")
            End If

            If (Not String.IsNullOrEmpty(Me.NavigateURL) AndAlso Me.Enabled) Then
                ' Set the href to be our navigateUrl.
                writer.AddAttribute(HtmlTextWriterAttribute.Href, Me.ResolveUrl(Me.NavigateURL))
            End If

            If (Me.Enabled) Then

                Dim customScript As String = Me.OnClientClick

                If (customScript.Length > 0 AndAlso Not customScript.EndsWith(";")) Then
                    customScript = customScript + ";"
                End If

                Dim opts As PostBackOptions = Me.GetPostBackOptions()
                Dim evt As String = Nothing

                If (opts IsNot Nothing) Then
                    evt = Me.Page.ClientScript.GetPostBackEventReference(opts)
                End If

                ' The onclick now becomes our postback, and the appended custom script.           
                writer.AddAttribute(HtmlTextWriterAttribute.Onclick, String.Format("{0}; {1} return false;", evt, customScript))

            End If

        End Sub

    End Class

  • Different SQL between C# and vb.net using LINQ to SQL causes performance issues

    Hi All,

    I am currently working on a project and we are using VB.NET, I am using LINQ to SQL for my data access. I have just implemented my search query and thought I would check the generated SQL's execution plan and found that the subtree cost was about 7.3. I know that I get different SQL between C# and VB.NET when using LINQ to SQL, as VB.NET seems to add a WHERE COALESCE instead of the straight WHERE that C# will do. In the past I did a quick check on a small query to see if it would make a difference and found that there was not a noticable one.

    Now having a larger more complex query I thought I would check the execution plan for the same query but written in C#, I now get a much smaller SQL query and the subtree cost drops from 7.3 to 0.1. A big difference IMO. Has anyone come across this before and what are your throughts on this. It baffles me that you would get such a difference in queries between the two languages.

  • Stop IE Flickering Between Pages

    I dont know if anyone has noticed but in IE when you click between pages in your site that have common elements i.e. a header. Your page will flicker for a brief moment. But in FireFox the page will not flicker and it will look smooth. I came across a fix for IE that will make this smooth just like in firefox.


    To use simply add the following 2 tags into your <head> section on your page:

  • Gotcha with linq and paging

    Hey All,

    Had a query which I was paging on the front end. I knew that a certain product was meant to be in my display but could not see it. But on page 2 a product would repeat itself. Odd, got into profiler and looked at the queries. The first page would get a select top 9 which would not do any orderby, the next page would have a query like so: SELECT ROW_NUMBER() OVER (ORDER BY [t15].[test], [t15].[ID], [t15].[CreatedDate] which was ordering by all my columns.

    So I added an orderby to my LINQ query which ordered my results by ProductName, then the paging was working as expected. Had another look in profiler and now I had what I expected.


    So a warning to all, make SQL Profiler your best friend because if you are not careful you could get spanked by LINQ.


    Thanks

    Stefan

  • Issues using HyperLink control with an image in a URL Rewriting scenario

    Hey All,

    I was using the HyperLink control in my page and added URL Rewriting to my page so that for example:

    http://site/test/test/default.aspx would be rewritten to http://site/default.aspx. I had a HyperLink control on the default page like so:

    <asp:HyperLink ID="hl1" runat="server" NavigateUrl="~/test.aspx" ImageUrl="~/test.jpg" Text="A"></asp:HyperLink>

    And I was getting the dreaded error: Cannot use a leading .. to exit above the top directory...

    Looking into this a little more if you remove the ImageURL property or even set it to be /test.jpg it will work fine, so conluded it must be something to be with the ImageUrl property in the control. Digging into reflector it looks like that when the HyperLink control renders it creates a new Image object and sets the ImageUrl of that to be ResolveClientUrl(url), internally the Image control also does a ResolveClientUrl again on that URL and I think this is where the issue is.

    My solution was to create a FixUrl method in my utility class which would convert replace ~/ in a url with the current application base path hence giving me an absolute URL. This is also handy to use in your pages to set the urls of your CSS, JS etc.


    Public Shared Function FixUrl(ByVal inURL As String) As String
            Return If(inURL.StartsWith("~"), _
                      HttpContext.Current.Request.ApplicationPath & inURL.Substring(1), _
                      inURL).Replace("//", "/")
    End Function


    I would now assign my ImageUrl property in code i.e. img1.ImageUrl = FixURL("~/test.jpg") and this now works well.


    If anyone has come past this before suggestions or ideas they would be appreciated.


    Thanks

    Stefan

  • EventValidation issues with asp.net ajax and FireFox caching causing issues...

    Was having some wierd issues with asp.net ajax in firefox. If for example you put a textbox and a button in an updatepanel and put in a value and click the button. Then you hit F5, in IE the value will be gone, but in FireFox the value is still there. This is due to firefox caching input values. The only way to clear that textbox in FF is to do a ctrl + F5. I had an issue in a paged datagrid where if you paged to say page 5, hit F5 it would be at page 1, hit nextpage and it would be back at 5. This had me stumped until I realised that firefox is caching the values and most likely the __VIEWSTATE hidden field is being cached and this is causing the issues. So I added this to my page load:

    Response.Cache.SetNoStore()


    This made firefox work but this turns off client caching which might not be a good idea. A developer (Steve) at work had a form with a button and textbox which in FF would not remember the value, this was a real WTF moment. I got his code and double checked the differences between them. The only thing different was that in his form he had autocomplete="off" set on the form due to using an autocomplete extender. I added this to my form and presto it was working perfectly. This was ok but you might not want to turn autocomplete off for your whole form so what can we do:

    Solution:


    Thinking about this I thought of what fields could affect this. Looking at a page you have the following hidden fields:

    __VIEWSTATE, __EVENTTARGET, __EVENTARGUMENT, __EVENTVALIDATION.


    I decided to try and turn of autocomplete for only these fields using some script at the bottom of my page:

    <script>
           function setAutoCompleteOff(id) {
                var elem = document.getElementById(id);
                if(elem) {
                    elem.setAttribute('autocomplete', 'off');
                }           
            }
           
            setAutoCompleteOff('__VIEWSTATE');
            setAutoCompleteOff('__EVENTTARGET');
            setAutoCompleteOff('__EVENTARGUMENT');
            setAutoCompleteOff('__EVENTVALIDATION');
    </script>


    Then I turned autocomplete back on on the form, and gave it a go, and to my supprise it worked perfectly. Now FF was not using sending over the cached values on hitting F5 and was using the original values. This meant my page works fine. One more thing is you can now turn on EnableEventValidation on your page and it seems to work fine now.