Chrome unresponsive during loop in MVC view - asp.net-mvc

I have a view that simply populates the page with objects from a list in my model, but during this, Google Chrome becomes unresponsive and asks whether we want to kill the pages. This is a bit frustrating as IE and FF both work fine (loads instantaneously) and I am not about to start recommending users use IE as a short-term solution (just can't bring myself to do it).
Here is an example of where the page is dying. The loop is populating rows in a table:
For i = 0 To Model.ListOfStuff.Count - 1
#<tr>
<td>#Html.LabelFor(Function(d) d.ListOfStuff(i).SelectedItem, Model.ListOfStuff(i).Name)</td>
<td>
#Html.CheckBoxFor(Function(c) c.ListOfStuff(i).SelectedItem)
#Html.HiddenFor(Function(c) c.ListOfStuff(i).Id)
</td>
</tr>
Next
This contains no more than 900 records, so I'm not sure why Chrome is falling over at this.
So my question to SO, is, how do I optimise this so that Chrome does not fall over? OR, is there a known work around for Chrome becoming unresponsive? I'm clutching at straws here.
Many thanks for any help.

In case anyone stumbles across this and is in a similar position, here is the solution to the problem.
The problem was that I was including jquery-1.7.1.js in my shared _Layout.vbhtml view, in a bundle. For some reason, although no jQuery was actively being called, this caused multiple views to crash if they included loops with quite a few records in them.
To fix this, I created a new shared layout view called "_LayoutNoScripts.vbhtml" (and removed all scripts) and set the problematic view's Layout to this instead:
#Code
Layout = "~/Views/Shared/_LayoutNoScripts.vbhtml"
#End Code
Then, because jQuery was actually needed in the view, I included the script as an individual reference:
<script src="#Url.Content("~/scripts/jquery-1.7.1.js")"></script>

Related

Refresh the browser once on load or clear DOM

I have a dynamic MVC4, jQuery Mobile application that works for the most part quite well. I have an auto posting dropdown list that selects a list from the database via the following code.
<script type="text/javascript">
$(function () {
$("#TownID").live('change', function () {
//$("#TownID").change(function () {
var actionUrl = $('#TheForm1').attr('action') + '/' + $('#TownID').val();
$('#TheForm1').attr('action', actionUrl);
$('#TheForm1').submit();
});
});
</script>
<p>
#using (Html.BeginForm("SearchTown", "Home", FormMethod.Post, new { id = "TheForm1" }))
{
#Html.DropDownList("TownID", (SelectList)ViewBag.TownId, "Select a Town")
}
</p>
The problem is it only works properly the first time a search is performed unless I click refresh. I don’t think this has anything to do with MVC, I think the problem is with AJAX and jQuery Mobile.
Edit:
The first time I search www.mysite.com/Home/Search/2 yields a result and woks fine, but the second time something seems to be left behind in the DOM??? and it looks for:
www.mysite.com/Home/Search/2/2 also
I get 404 errors in my log and “Error Loading Page” but it still finds the results and displays the page correctly!
Then with a third search I get the error 404’s in my log and “Error Loading Page” but it has grown and now looks for:
www.mysite.com/Home/Search/2/2
www.mysite.com/Home/Search/2/2/2 also
This then continues to grow after every search until at some seemingly random point on each test, it seems to give up and I get error 505
Additional Edit:
The code works perfectly if I take jQuery Mobile out of the question
Can anyone tell me what might be going on here?
Get rid of: $(function () {
And replace it with: $(document).delegate('[data-role="page"]', 'pageinit', function () {
Please read the big yellow sections at the top of this page: http://jquerymobile.com/demos/1.1.0/docs/api/events.html
You can't rely on document.ready or any other event that only fires once per page. Instead you have to get used to using jQuery Mobile's custom page events like pageinit so your code will work no-matter when the page is added to the DOM (which you don't know when this will happen in a jQuery Mobile website). There are a ton of events, so again, please read the documentation I linked-to above.
Firstly, dynamically generated html using a server side templating engine blows. I really don't understand what value people see in it.
My guess is that it used to make sense 10 years ago before AJAX became popular, and has just hung in there ever since because people have this feeling that it is "the right way to do it". It isn't. ESPECIALLY for mobile web apps.
Secondly, it looks like you are trying to do pretty simple search. All this MVC4 garbage makes it difficult for you to see what is really happening though. You don't need to append parameters to your URL for a simple form submission like this. In fact your TownId should already be part of the POST data when you submit, so you can just remove the URL modification bit.
Alternatively, don't use a form submission, but just a GET and AJAX. I don't know what your app is doing here, but I imagine you want to display the results on the page dynamically somehow, so a GET is more than enough.
Use your developer browser tools (F12) to see what exactly is getting submitted when you do the submit - it really helps. And for your next project, abandon MVC4! "Well established design patterns" my foot.
I have been bothered by this problem for a long time
There are same select element in the DOM I think so...
and I used $('.SelectCSS:last').val()
It seen work well.
I come from China , English is poor...
I guess this is one for the future, MVC and jQuery Mobile don't seem to blend completely right now. Maybe MS's response to the issue is Single Page Applications!
SPA may satisfy Danial also?

How can I make code indentation behave correctly in vbhtml razor files?

This is driving me round the bend. I'm a long time VB.NET forms developer, quite new to ASP.NET and completely new to MVC. I'm creating vbhtml pages that use the VB.NET Razor syntax, and I seem to be constantly fighting against the UI which is trying to indent my code incorrectly. Take the following example, based on the template page for a new Razor view:
#Code
Layout = Nothing
End Code
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<div>
#If True Then
#<ul>
#For x = 1 To 2
Next
</ul>
End If '<-- Randomly indented too far
</div>
</body>
</html>
In the above example, as soon as I hit return after Next, End If two lines below randomly jumps two tabs forward from where it should be. In other examples I've hit a circle where pushing one line to the correct place throws another line out of position and vice versa.
I'm so annoyed at this point I'd be happy to disable auto-indentation completely and just manage it myself, but I can't even find out how to do that! Following advice on another thread I disabled indentation for HTML pages but all that stops is indentation of HTML tags - the code blocks still slide around all over the place.
I thought an extension might be causing the problem but I disabled them all and restarted and the problem remains. Am I doing something fundamentally wrong? I find it hard to believe Microsoft would release something so poor so it seems more likely I'm just not using it right.
I found a solution (of a fashion) on another question (I really did search hard before posting this question and couldn't find anything): Why doesn't Visual Studio code formatting work properly for Razor markup?
Essentially the solution seems to be to ensure that your code uses spaces instead of tabs for the whitespace. Whilst increasing the overall size of the page because of increased whitespace, it does lessen the problem (whilst not eliminating it completely). On the linked thread, someone who appears to be connected with Microsoft has acknowledged it is indeed a bug related to the overlapping formatters for HTML and VB.NET which they hope to improve in a new release. I've dropped to 2 spaces per indent to lessen the bandwidth impact.
Thanks to the guys who contributed.
A better alternative here(rather than using spaces for tabs), is to change the block indenting for HTML and C#/VB to "Block" instead of "Smart". This isn't a full solution, but IMO is a far less painful work-around than using spaces!

Slowness in Orbeon page rendering when showing a group with a large number of fields

I am working on Orbeon forms and i have a performance related issue as explained below.
I have a form where I have five fields initially. On the fifth dropdown field, if I select "Yes", because of xforms:group it shows a block of fields (the block has around 40 fields).
Since the block is in the repeated section, I can add/delete as many blocks as I can.
Now, if I add say 10 blocks and when I toggle the fifth dropdown field from any value to "Yes", it takes more than 2 seconds to display all the blocks.
I am using Orbeon Forms 3.8 and Tomcat 6 on Windows XP desktop with 2GB RAM.
Please let me know what happens when "Yes" is selected (meaning conditional display when xforms:group is true) which is taking more time to display.
<xforms:group ref=".[instance('form-attributes')/flag='yes']" >
//code for the controls here
</xforms:group>
If you are using code that looks like:
<xforms:group ref=".[condition]">
<!-- Large number of fields -->
</xforms:group>
When condition is false, the fields inside the group are non-relevant. The XForms engine doesn't compute their value, read-only status, validity, label, hint, help, alert, etc.
When condition becomes true, the content of the group become relevant, and the XForms engine evaluates all the controls inside the group.
The browser needs to apply all those changes to the DOM.
Typically, step #2 is much faster than #3, especially with IE7. To avoid the numerous updates on step #3, another way to write this code is:
<xhtml:div class="{if (condition) then '' else 'xforms-disabled'}">
<!-- Large number of fields -->
</xhtml:div>
With this, the fields inside the div will always be relevant:
The upside is that when condition becomes true, all the browser might need to do is to flip that class on the div. It won't necessarily need to update all the controls inside, unless of course their value has also changed.
The downside is that while condition is false, the XForms engine, on the server, needs to keep all the controls inside the div up-to-date.
But more often than not, especially when you're seeing IE7 slowness, the performance you gain on the client far outweighs the increased processing that might be needed on the server.
I found this link that seems to suggest span tag instead of div tag, though the original post was for Code crash, the suggested work around gave a small performance improvement in my form when I tested it in IE. Hope this code will give you some benefit.

Firefox 4 doesn't render partial pages

I have an ASP.NET MVC page which contains a table, where every row takes some time to load. So I'm calling Response.Flush() after every row is rendered.
IE9 behaves the way it should: displays rows one by one. FF4 on the other hand, displays the page only when it finished loading completely, even though I can see in FireBug's Network tab that the rows are being received one by one.
Is there something I could be doing wrong on the server-side? If not, is there something I can do to my Firefox, so that it displays the page the way I want?
I would try using AJAX to fill the table. Maybe a row per call, maybe whole set at once.
Consider closing your document with </html> and add the extra rows in script; <script> tags may (in practice) follow </html>. Not a real AJAX solution, not strictly correct, but potentially a lot easier on your serverside.
A similar, but more correct solution would be to insert the script just before the </body>.
See also When does reflow happen in a DOM environment?

Rendering complete page and not "progressively" (using struts 2 / tiles)

Is there a way to get struts 2 (using tiles) to build the whole page before sending it to the browser? I don't want the page to be build "progressively" in the browser one part at a time.
The main problem I'm trying to solve is that internet explorer 7 flashes/blinks the page even if only some of the content changes (firefox does this much more smoothly).
So that if I have a page with:
HEADER
some content
FOOTER
And the "some content" area only changes between page loads, the FOOTER part still flashes the white background before filling it with the background color of the footer. I tought that maybe by getting struts to send the complete page it would load fast enough to eliminate the "blinking".
Now the FOOTER comes from the server a little bit later than the parts before it and so it flashes (in internet explorer, firefox displays the page smoothly).
NB: this is an important requirement for the site, and using ajax to load the middle content is out (as are frames or other "hacks"). The site is built using CSS and not a table layout, maybe I will have to use a table layout to get it to work...
About using tiles flush parameter:
I tried that and it doesn't work as I need. I would need a flush-parameter for the whole page. I have tried the normal jsp page directive "autoFlush=false" but it didn't work. I set this directive on my main template page (and not in the tiles).
Here is an example from the main template, which uses header, body and footer templates. With the Thread.sleep() I added the problem is easy to spot. The footer renders 2 secs later than the rest of the page.
<body>
<div id="container">
<t:insertAttribute name="header" flush="false" />
<div id="content"><t:insertAttribute name="body" flush="false"/></div>
<div class="clear"></div>
<% Thread.sleep(2000); %>
<t:insertAttribute name="footer" flush="false" />
</div>
</body>
UPDATE
Thanks for the comments. The requirement is actually almost reasonable as this isn't a normal web page, think embedded.
But apparently there is no way of configuring IE to start rendering after some delay (like firefox has a configurable delay of some 100ms)?
I tried to intercept the TilesResult but the method doExecute is run before the whole content is apparently evaluated, so the method has already exited before the jsp is evaluated (my Thread.sleep() test). I was wondering how I could render the whole response to a string and then output that all at once to the browser.
I know that this isn't foolproof and network delays etc may factor in this, but if I could get the response to output all at once and maybe use a table based layout (IE possibly renders the table only after the table closes) this could work reasonably.
Or then try to get this switched to firefox or maybe forget all about this little glitch...
UPDATE 2
This started to bother me so I did some investigation.
If I had a plain jsp page (no tiles) the buffering works (with the buffer attribute), so that if I had my Thread.sleep() there the whole page rendered after two seconds if the page size was below the buffer size.
But if I used tiles in the page (as in the example above) I couldn't get the page to render at the same time (I even included the page directive in all my tiles-templates/"components", no help). So tiles probably flushes the response somewhere?
Furthermore, the "problematic tiles" was my body-part, which contained a struts:form tag. I replaced it with a normal form-tag and it worked as I wanted...
UPDATE 3
Ok, nobody seems to know the inner workings of tiles or struts tags...
No big problem as this is a very specific case and requirement.
I worked around it by using apache as a proxt in front of the application, and using apache's proxy configuration options to specify a large buffer.
I'll mark this as answered.
You can send page data all at once at the server end if you like (and many frameworks do that anyway for convenience) but the reality of networking is that it won't all arrive at once and the browser will render it as packets arrive. And this is a good thing for responsiveness, even if you* aesthetically would like the page to display all at once.
You can reduce the lag as much as possible by simplifying markup and using deflate compression to keep the payload size down, and that's a worthwhile thing to do in general. Plus you can make sure you're not hitting a Flash Of Unstyled Content. But you can't control when the browser chooses to render, short of doing it all in JavaScript with all the downsides that entails (and even then, the browser might redraw slowly).
(* - or your client/boss, if that's who has come up with this "important requirement" that your site somehow work differently to every other page on the web.)
Can you use the "flush" attribute on the tiles components?
<tiles:insertAttribute name="body" flush="false"/>
In addition if the output buffer gets too big, it will flush anyway. Try increasing the buffer size?
<%# page language="java" buffer="500kb" autoFlush="false" %>

Resources