Asp.net Mvc 2 DisplayFor Performance Issue? - performance

In my recent project which is using Asp.net Mvc 2, we found that the DisplayFor has performance issue. I'm not so sure whether it is the real issue or did I miss something?
I hope some Asp.net Mvc Guru can explain it to me. :)
Model.
public class Customer
{
public int CustomerId { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string EmailAddress { get; set; }
public static IEnumerable<Customer> GetCustomers()
{
for (int i = 0; i < 1000; i++)
{
var cust = new Customer()
{
CustomerId = i + 1,
Name = "Name - " + (i + 1),
Address = "Somewhere in the Earth...",
EmailAddress = "customerABC"
};
yield return cust;
}
}
}
Controller
public ActionResult V1()
{
return View(Customer.GetCustomers());
}
public ActionResult V2()
{
return View(Customer.GetCustomers());
}
V1 (which has performance issue)
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<Customer>>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
V1
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>V1</h2>
<table>
<%foreach (var cust in this.Model)
{%>
<%= Html.DisplayFor(m => cust) %>
<%} %>
</table>
</asp:Content>
And Template is
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Customer>" %>
<tr>
<td><%= this.Model.CustomerId %></td>
<td><%= this.Model.Name %></td>
<td><%= this.Model.Address %></td>
<td><%= this.Model.EmailAddress %></td>
</tr>
V2 (no performance issue)
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<Customer>>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
V2
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>V2</h2>
<table>
<%foreach (var cust in this.Model)
{%>
<tr>
<td><%= cust.CustomerId%></td>
<td><%= cust.Name%></td>
<td><%= cust.Address%></td>
<td><%= cust.EmailAddress%></td>
</tr>
<%} %>
</table>
</asp:Content>
I can easy see the performance difference between V1 and V2.
EDIT: When I deploy to my local IIS 7 (with Release version) and it (V1) becomes very fast. The issue is solved, but I still want to know the reason. :)
Thanks,
Soe Moe

Caching is enabled only in release mode. If you run the application in debug mode, you might see a performance hit due to disk accesses.
See also:
http://codeclimber.net.nz/archive/2009/04/22/how-to-improve-htmlhelper.renderpartial-performances-donrsquot-run-in-debug-mode.aspx

The issue is that DisplayFor() uses a lambda expression which is compiled and executed at runtime.
Therefore, the performance difference in V1 can be attributed to this "intermediate" compilation step.
V2 is simply a property access which does not need any compilation.
I'm taking a guess here, but I imagine that IIS7 is smart enough to keep a cached copy of the view (and the compiled lambda expressions) around for future re-use, meaning subsequent render times will be comparable to V1 in IIS 6.

Related

MVC pagedlist.mvc and aspx view

I have got a page where im using the Nuget package pagedlist.mvc 3.0.18 (The latest version for MVC3). The problem is that when i'm listing the pages its makes my pages into a list of which look like
previous
1
2
3
4
next
Instead of < 1,2,3,4,5,6,7.. >
My view looks like
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IPagedList<News>>" %>
<%# Import namespace="PagedList" %>
<%# Import namespace="PagedList.Mvc" %>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<table>
<tr>
<td>
<% foreach (var v in Model)
{%>
<%: v.Content %><br />
<%: v.DateCreated %><br />
<%: v.Email %><br />
<%} %>
<h2>News</h2>
<%: Html.PagedListPager(Model, page => Url.Action("News", new { page }), PagedListRenderOptions.Minimal)%>
Code behind looks like
public ActionResult News(int? page)
{
List<News> products = HomeBLL.GetNewsList(); //returns IQueryable<Product> representing an unknown number of products. a thousand maybe?
var pageNumber = page ?? 1; // if no page was specified in the querystring, default to the first page (1)
var onePageOfProducts = products.ToPagedList(pageNumber, 25); // will only contain 25 products max because of the pageSize
ViewBag.OnePageOfProducts = onePageOfProducts;
return View(onePageOfProducts);
}
Any suggestions on what could be wrong? The standard CSS is included as well.
You should include PagedList.css in your View (it is located in Content folder).
It seems that the newest package of pagedlist is NOT supported for the aspx views, unless you reach a low level of this package.
Include the css file PagedList.css inside HEAD tags in your _Layout page or at the top of your viewpage.

How can I change this ASP syntax to Razor?

How can I convert this to ASP.NET?
Or how can I convert ASP to Razor, what will I add or remove and what are the things to remember while converting ASP to Razor or reverse.
<%# Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<PopulatingDDLusingEF.ViewModels.IndexViewModel>" %>
<%# Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<PopulatingDDLusingEF.ViewModels.IndexViewModel>" %>
In Razor you should use #Model keyword
#model PopulatingDDLusingEF.ViewModels.IndexViewModel
#{
ViewBag.Title = "Result";
Layout = "~/Views/Shared/Site.Master";
}
This is an example how to convert ASP syntax to razor syntax which i got from Marcind's post
<% if(someCondition) { %>
<ol>
<% foreach(var item in Model) { %>
<li><%: item.ToString() %></li>
<% } %>
</ol>
<% } %>
Can be expressed as follows in Razor:
#if(someCondition) {
<ol>
#foreach(var item in Model) {
<li>#item.ToString()</li>
}
</ol>
}
Also check this for a quick useful Razor reference

Validating TextBox input for a list that is a property of an MVC3 ViewModel

I realize I'm a little late to the party, but... I'm working in my first MVC project, and have been able to get a handle on most of what needs to be done. Most of the project simply reads data and pumps the data into charts. However, I have one View whose model looks like this (the parent class properties are not important here):
public class Class1 : ParentClass
{
public List<ChildClass> ChildClassList{get;set;}
}
and the ChildClass looks like this:
public class ChildClass
{
public int Property1{get;set;}
public int Property2{get;set;}
public string Property3{get;set;}
public int? ID{get;set;}
[Editable(true)]
public decimal? Property4{get;set;}
}
Now, retreiving the data is not an issue. I can loop through the list, and create a table for editing like this:
<% foreach(var g in Model.ChildClassList){%>
<tr>
<td style="text-align: right;">
<%= Html.Label(g.Property3)%>
</td>
<td>
<%=Html.TextBox(Model.ParentProperty.ToString() + "_" + g.Property2, (g.Property4.HasValue ? g.Property4.Value.ToString("C") : "$0.00"))%>
</td>
</tr>
<% }%>
After cruising through this site for the past couple of days, it dawned on me that I can validate the input on the server-side, in the POST method (there is a "Save" button at the bottom of the form), but (a)how do I get the validation error message back to the user, (b)perform the validation client-side?.
I must mention also that this view uses the values in the list to create a portion of a chart, prior to being rendered as a table.
On the server-side in the [HttpPost] action, you can check the validity of the model like this:
[HttpPost]
public ActionResult Save(Class1 model)
{
if (!ModelState.IsValid)
return View(model);
// Code to save model.
}
You also need to update your View to show the errors:
<%= Html.ValidationSummary(false, "Please fix these errors.")
<% foreach(var g in Model.ChildClassList){%>
<tr>
<td style="text-align: right;">
<%= Html.Label(g.Property3)%>
</td>
<td>
<%=Html.TextBox(Model.ParentProperty.ToString() + "_" + g.Property2, (g.Property4.HasValue ? g.Property4.Value.ToString("C") : "$0.00"))%>
<%= Html.ValidationMessageFor(model => g.Property4)
</td>
</tr>
<% }%>
If you want to enable it client-side, you need to use unobstrusive client validation, which you can do by updating your web.config:
<configuration>
<appSettings>
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
</appSettings>
</configuration>
Also you need the following JS libraries:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" type="text/javascript"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js" type="text/javascript"></script>
<script src="//ajax.microsoft.com/ajax/jQuery.Validate/1.7/jQuery.Validate.min.js" type="text/javascript"></script>
<script src="//ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>
On a side note, try and avoid loops to render out your View. It's unnecessary code soup, which can be avoided by the use of editor templates.

jQuery client side validation not working with MVC 3 MvcContrib.FluentHtml

Using MVC 3 RTM and MvcContrib/FluentHtml version 3.0.51.0, I can't get the jQuery client side validation to work. Server side validation works fine, and returns showing the correct validation summary, etc. But the form post always tries to hit the server-side post controller action when it should have stopped on the client side to display the validation error.
Any ideas of what I'm missing? Could the latest version of MvcContrib/FluentHtml be incompatible with jQuery client validation?
Here's my code:
Web.config has:
<add key="ClientValidationEnabled" value="true"/>
<add key="UnobtrusiveJavaScriptEnabled" value="true"/>
Site.Master page has:
<script src="<%= Url.Content("~/Assets/JavaScript/jquery-1.4.4.min.js")%>" type="text/javascript"></script>
<script src="<%= Url.Content("~/Assets/JavaScript/jquery-ui-1.8.7.min.js")%>" type="text/javascript"></script>
<script src="<%= Url.Content("~/Assets/JavaScript/jquery.validate.min.js")%>" type="text/javascript"></script>
<script src="<%= Url.Content("~/Assets/JavaScript/jquery.validate.unobtrusive.min.js")%>" type="text/javascript"></script>
View page inherits from MvcContrib's ModelViewPage:
Here's the view page:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="ModelViewPage<MaintainReferralAgencyDetailVM>" %>
<%# Import Namespace="OASIS3G.Controllers" %>
<%# Import Namespace="OASIS3G.ViewModels" %>
<%# Import Namespace="JCDCHelper.Extension"%>
<%# Import Namespace="MvcContrib.FluentHtml" %>
<%# Import Namespace="System.Web.Mvc" %>
<%# Import Namespace="System.Web.Mvc.Html" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<% using (Html.BeginForm()) %>
<% { %>
<h1>Referral Agency Detail</h1>
<%= Html.ValidationSummary(false) %>
<table class="NoBorder">
<tr>
<td class="NoBorder SubmitFormLeftColumn"><span class="required">* </span>Zip Code:</td>
<td class="NoBorder"><%= this.TextBox(x => x.ReferralAgency.ContactInformation.Zipcode) %> Example: 99999 or 999990000
<%= Html.ValidationMessageFor(x=>x.ReferralAgency.ContactInformation.Zipcode) %>
</td>
</tr>
</table>
<input type="submit" value="Submit" />
<% } %>
</asp:Content>
Here's the controller post action:
[HttpPost]
public ActionResult MaintainReferralAgencyDetail(MaintainReferralAgencyDetailVM userInputs)
{
// I shouldn't reach this when I submit the form with a blank Zipcode, but I do:
if (ModelState.IsValid)
{
Here's the entity object with the Required field:
[Serializable]
public class ContactInformationEO
{
public virtual Int64 AddressId { get; set; }
[Required]
public virtual string Zipcode { get; set; }
I figured it out, it's definitely MvcContrib messing it up. I originally thought MvcContrib wasn't a factor because when I had changed from MvcContrib's ModelViewPage to Mvc.ViewPage, I switched the "this.TextBox" to "Html.TextBox", it still didn't work. However, I just discovered that I need to switch the control to "Html.EditorFor" instead of "Html.TextBox".
I've googled for a few minutes and it doesnt look like MvcContrib version 3.0.51.0 supports jquery client-side validation with any equivalent of EditorFor, so I'll have to just rip it out and use the native MVC controls.
You can see an article with a complete solution of my approach here: automatically-validate-and-format-data-with-asp-net-mvc-and-jquery
Just ran headlong into this problem, looks like Scott Kirkland has a solution.

How can I get the total number of items in a SQL result?

I have the following code:
[code]
<h2>Listado General de Carreras</h2>
<% foreach (var item in Model)
{ %>
<p><span class="titulo"><%=Html.ActionLink(item.Nombre, "Details" , new { id = item.ID }) %></span> <sub> Area: <%: item.Area.Nombre%></sub></p>
<% } %>
<p>
<%: Html.ActionLink("Crear Nueva Carrera", "Create") %>
</p>
[/code]
What I want to do is display a header for every Area in my database and under each area show what Careers the Area has.
How can I efficiently do this with MVC2?
I was thinking of using Linq querys and saving them to the ViewData[] but maybe there is another way?
have you tried the .Count property on the collection?

Resources