I have a classic asp.net page in .net 4.6.1.
It loads 4 MB of data (they want it on one page) and no matter I simplify it, the IIS Worker Process w3wp.exe eats up a Gig of data, and never expires anything or gives any memory back.
Why?
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="MainContent" runat="server">
<asp:GridView ID="gvSelectionList" runat="server" AutoGenerateColumns="false" CssClass="LPSCriteriaSelection" EnableViewState="False">
<Columns>
<asp:TemplateField HeaderText="SerialNumber">
<ItemTemplate>
<asp:HyperLink ID="hlSerialNumber" Text='<%#GetSerialNumberText(Container.DataItem)%>' />
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
</asp:Content>
Here's the code
using System;
using System.Collections.Generic;
using System.Web.UI;
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
if(this.IsPostBack) return;
ExpandableSelections items = new ExpandableSelections();
if(items.Count == 0) return;
this.gvSelectionList.DataSource = items;
this.gvSelectionList.DataBind();
}
protected string GetSerialNumberText(object dataItem)
{
SerialNumberData item = (SerialNumberData)dataItem;
return item.SerialNumber;
}
}
public class SerialNumberData
{
public string SerialNumber { get; set; }
public SerialNumberData(string data) { SerialNumber = data; }
}
public class ExpandableSelections : List<SerialNumberData>
{
internal ExpandableSelections()
{ // Emulate database call
for (int i = 1; i < 72000; i++)
this.Add(new SerialNumberData("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"));
}
}
A call to Microsoft revealed calling .Dispose() on the grid itself will make it more readily available to Garbage Collection, but in this example the GC thread was often blocked (said they couldn't see by what -- antivirus?) and, because we only needed a read-only GridView,
I found it far better to simply replace the GridView with a classic <% FunctionCall(); %> and in that call write the html out directly with Reponse.Write().
This used far less RAM and would always return it on subsequent page loads.
Related
I have following project structure where web application may contain user controls from the same web project or from a separate class library. The issue is in Default.aspx.cs, when I execute usercontrol2.SetValues(); I receive NullReferenceException since for some reason textbox2 is null. I've tried using EnsureChildControls(); but it does not help either. Should I register or invoke these usercontrols in some other way? Why does not it work out-of-box?
User control in web project
WebUserControl1.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl1.ascx.cs" Inherits="WebApplication1.WebUserControl1" %>
<asp:TextBox runat="server" ID="textbox1"></asp:TextBox>
WebUserControl1.ascx.cs
namespace WebApplication1
{
public partial class WebUserControl1 : System.Web.UI.UserControl
{
public void SetValues()
{
textbox1.Text = "Hello";
}
}
}
User control in class library
WebUserControl2.ascx
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="WebUserControl2.ascx.cs" Inherits="ClassLibrary1.WebUserControl2" %>
<asp:TextBox runat="server" ID="textbox2"></asp:TextBox>
WebUserControl2.ascx.cs
namespace ClassLibrary1
{
public partial class WebUserControl2 : System.Web.UI.UserControl
{
public void SetValues()
{
textbox2.Text = "world";
}
}
}
Main page
Default.aspx
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/Site1.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
<%# Register tagPrefix="web" tagName="WebUserControl1" src="WebUserControl1.ascx" %>
<%# Register TagPrefix="web" Namespace="ClassLibrary1" Assembly="ClassLibrary1" %>
<asp:Content ID="BodyContent" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
<web:WebUserControl1 runat="server" ID="usercontrol1"></web:WebUserControl1>
<web:WebUserControl2 runat="server" ID="usercontrol2"></web:WebUserControl2>
</asp:Content>
Default.aspx.cs
using System;
using System.Web.UI;
namespace WebApplication1
{
public partial class _Default : Page
{
protected void Page_Load(object sender, EventArgs e)
{
usercontrol1.SetValues(); // OK
usercontrol2.SetValues(); // NullReferenceException
}
}
}
Using ascx usercontrols from a different assembly is not possible.
I think you should look at this problem this way. Your classlibrary is compiled into a dll-file. This is the only thing that is available for your webapplication. The ‘ascx’ doesn’t get compiled into the dll, and is not available.
If you really want to keep some controls separated from your web-project, I think there are a few options:
Convert your usercontrol to a customcontrol. Custom controls are a bit more difficult to create, but it is certainly not impossible. This way you really get a re-usable control.
See also this question; it addresses your problem and there’s also a link to an algorithm which ‘converts’ an ascx usercontrol to a custom control. (I didn’t test that)
Asp.NET user control referenced from another project/dll has NULL properties
Make sure your ascx files are available to the web-project, by publishing to a path in your output. Then use LoadControl to load them serverside. This could work, but I also think some of the reusability from your classlibrary is lost.
I have a situation where I need to create multiple code behind files for a single .aspx page in c# asp.net. Actually I have a web form on that huge coding is done and I need multiple developer's working on it simultaneously. How can I achieve the same?
Here is the code snippet I tried
Class 1 MyPartialClass.cs
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
protected void PrintText(string pt)
{
Response.Write(pt);
//lblTest.Text = pt; //Can not access this label in partial class.
}
}
}
Class 2 which is Default.aspx.cs
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
PrintText("Hello World");
}
}
}
and my HTML source
<%# Page Language="C#" AutoEventWireup="false" CodeBehind="Default.aspx.cs" Inherits="WebApplication1.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="lblTest" runat="server"></asp:Label>
</div>
</form>
</body>
</html>
ASP.NET will always generate your code behind files as partial classes
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
}
}
You can therefor separate the code behind in different files, if you pertain the definition as partial and keep the class under the same namespace.
Edit : The Web Project
//Default.aspx
<%# Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="WebApplication1.Default" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
<asp:Label ID="lblTest" runat="server" Text="Label"></asp:Label>
</asp:Content>
//Default.aspx.cs
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
PrintText("Hello World");
}
}
}
//MyPartialClass.cs
namespace WebApplication1
{
public partial class Default
{
protected void PrintText(string pt)
{
Response.Write(pt);
lblTest.Text = pt; //lblTest is accessible here
}
}
}
I haven't modified any other generated files. One thing I like to mention is that the Default.aspx.cs file that has been generated was generated with the class name "_Default". I have changed it to Default and Visual Studio refactored the change across all files that contain a definition for that class, except the Default.aspx file, where I had to manually modifiy from Inherits="WebApplication1._Default" to Inherits="WebApplication1.Default".
Edit 2:
I kept searching the internet, and according to http://codeverge.com/asp.net.web-forms/partial-classes-for-code-behind/371053, what you are trying to do is impossible. Same idea is detailed at http://codeverge.com/asp.net.web-forms/using-partial-classes-to-have-multiple-code/377575
If possible, consider converting from Web Site to Web Application, which supports what you are trying to achieve. Here is a walkthrough on how to perform this conversion: http://msdn.microsoft.com/en-us/library/vstudio/aa983476(v=vs.100).aspx
You need to set up a source safe server in order to that, like Team Foundation Server.
You can easily just add partial classes to your code.
http://www.codeproject.com/Articles/709273/Partial-Classes-in-Csharp-With-Real-Example
i am trying to get that AjaxFileUpload-Control(used in ContentPage) working. But it does not fire OnUploadComplete Event at server side
I am using version 4.1.60919.0 of the ControlToolkit. I have tried everything i found on the internet.
Here just a few steps:
Added enctype="multipart/form-data" method="post" to the form-element in my MasterPage
Nested the AjaxFileUpload into an UpdatePanel with UpdateMode=Always
Tried events UploadedComplete and OnUploadComplete, but stayed at the second one
Added a try-catch-block in the EventHandler to catch unknown exceptions and print the ExceptionMessage to a label on the site --> nothing happened
Tried it with(out) a ThrobberImage...
Many other tipps that did not work...
So, i hope we will find a solution together in this community. Heres my markup:
<%# Page Title="New Download" Language="C#" MasterPageFile="~/MasterPage.master" AutoEventWireup="true" CodeFile="NewDownload.aspx.cs" Inherits="Internals_NewDownload" %>
<asp:Content ID="Content1" ContentPlaceHolderID="HeadContent" runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="Server">
<ajax:ToolkitScriptManager ID="ToolkitscriptManager" runat="server"> </ajax:ToolkitScriptManager>
<h1>Create a new Download</h1>
<ajax:AjaxFileUpload ID="FileUpload" runat="server" ThrobberID="ThrobberLabel" OnUploadComplete="FileUpload_UploadComplete" />
<asp:Label ID="ThrobberLabel" runat="server" Style="display: none;"><img alt="UploadingPicture" title="Please wait while uploading..." src='<%= Constants.DomainString + "/Data/Images/loading-small.gif" %>' /></asp:Label>
<asp:Label ID="DownloadLabel" runat="server"></asp:Label>
</asp:Content>
And this is my CodeBehind:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class Internals_NewDownload : System.Web.UI.Page
{
private string m_LanguageCode;
protected void Page_Load(object sender, EventArgs e)
{
if (RouteData.Values.ContainsKey("LanguageCode"))
m_LanguageCode = RouteData.Values["LanguageCode"].ToString();
//if (IsPostBack)
// return;
if (!User.IsInRole("Administrator") && !User.IsInRole("Kunde") && !User.IsInRole("Mitarbeiter"))
Response.Redirect(Constants.DomainString + "/PermissionDenied.aspx");
Session[Constants.NonGlobalizedString] = true;
Session[Constants.MenuInfoSession] = new ClsMenuInfo("NewDownload");
}
protected void FileUpload_UploadComplete(object sender, AjaxControlToolkit.AjaxFileUploadEventArgs e)
{
try
{
string filePath = "~/upload/" + e.FileName;
DownloadLabel.Text = filePath;
}
catch (Exception ex)
{
DownloadLabel.Text = ex.Message;
}
}
}
Please, if you have ANY idea, do not hesitate to let me know it. I am very confused as i think that i just did in that howtos i found on the internet...
Thanks in advance!
Take into account that AjaxFileUpload control use contextkey QueryString parameter to detect own postback. I believe the reason of you issue is that this parameter lost in result of rewriting url.
I'm not expert in applying routing but in my opinion you need to register contextkey parameter in routing tables and tweak AjaxControlToolkit sources to use RouteData instead of Request.QueryString for retrieving it value.
Check this link for more info: AjaxControlToolkit Source Code
I'm thinking about converting a few usercontrols to use templates instead. One of these is my own UC which contains some controls, one of which is a repeater. Is it possible to specifcy a template for the second level usercontrol from the template for the first (which would be on the page)?
Assuming I understand your question correctly, try something like this:
Page.aspx:
<%# Page Language="C#" %>
<%# Register src="UC.ascx" tagname="UC" tagprefix="uc1" %>
<uc1:UC ID="UC1" runat="server">
<RepeaterTemplate>
<%# Eval("Name") %> <%# Eval("Age") %><br />
</RepeaterTemplate>
</uc1:UC>
UC.ascx:
<%# Control Language="C#" ClassName="UC" %>
<script runat="server">
class Person {
public string Name { get; set; }
public int Age { get; set; }
}
protected void Page_Load(object sender, EventArgs e) {
repeater1.ItemTemplate = RepeaterTemplate;
repeater1.DataSource = new Person[] {
new Person { Name="Joe", Age=20},
new Person { Name="Jack", Age=30},
};
repeater1.DataBind();
}
public ITemplate RepeaterTemplate { get; set; }
</script>
<asp:Repeater runat="server" ID="repeater1">
</asp:Repeater>
This basically passes on the template specified on the outer page to the repeater in the user control.
It may not be exactly your scenario, but hopefully that'll give you ideas.
I'm not sure I understand your question, but I do alot of multi-level repeaters with dynamic templates. I use UserControls with no code as a convenient place to put the template html.
In code behind (such as an ItemDataBound event from a parent repeater), I select the appropriate template and set it:
repeater.ItemTemplate = MyBase.LoadTemplate(templateControlName)
repeater.DataSource = dataSource
repeater.DataBind()
I'm trying to get a user control working asynchronously, yet no matter what I do it continues to work synchronously. I've stripped it down to its bare minimum as a test web application. This would be the user control:
<%# Control Language="C#" %>
<script runat="server">
SqlConnection m_oConnection;
SqlCommand m_oCommand;
void Page_Load(object sender, EventArgs e)
{
Trace.Warn("Page_Load");
string strDSN = ConfigurationManager.ConnectionStrings["DSN"].ConnectionString + ";async=true";
string strSQL = "waitfor delay '00:00:10'; select * from MyTable";
m_oConnection = new SqlConnection(strDSN);
m_oCommand = new SqlCommand(strSQL, m_oConnection);
m_oConnection.Open();
Page.RegisterAsyncTask(new PageAsyncTask(new BeginEventHandler(BeginHandler), new EndEventHandler(EndHandler), new EndEventHandler(TimeoutHandler), null, true));
Page.ExecuteRegisteredAsyncTasks();
}
IAsyncResult BeginHandler(object src, EventArgs e, AsyncCallback cb, object state)
{
Trace.Warn("BeginHandler");
return m_oCommand.BeginExecuteReader(cb, state);
}
void EndHandler(IAsyncResult ar)
{
Trace.Warn("EndHandler");
GridView1.DataSource = m_oCommand.EndExecuteReader(ar);
GridView1.DataBind();
m_oConnection.Close();
}
void TimeoutHandler(IAsyncResult ar)
{
Trace.Warn("TimeoutHandler");
}
</script>
<asp:gridview id="GridView1" runat="server" />
And this would be the page in which I host the control three times:
<%# page language="C#" trace="true" async="true" asynctimeout="60" %>
<%# register tagprefix="uc" tagname="mycontrol" src="~/MyControl.ascx" %>
<html>
<body>
<form id="form1" runat="server">
<uc:mycontrol id="MyControl1" runat="server" />
<uc:mycontrol id="MyControl2" runat="server" />
<uc:mycontrol id="MyControl3" runat="server" />
</form>
</body>
</html>
The page gets displayed without errors, but the trace at the bottom of the page shows each control instance is processed synchronously. What am I doing wrong? Is there a configuration setting somewhere I'm missing?
Looks like I can answer my own question. The user control should not be calling Page.ExecuteRegisteredAsyncTasks. By doing that, the control was adding the async task, running it, and waiting for it to complete.
Instead, each instance of the user control should call only Page.RegisterAsyncTask. After each control instance has done this the page automatically calls RegistereAsyncTask running all three registered async tasks simultaniously.
So here is the new user control:
<%# Control Language="C#" %>
<script runat="server">
SqlConnection m_oConnection;
SqlCommand m_oCommand;
void Page_Load(object sender, EventArgs e)
{
Trace.Warn(ID, "Page_Load - " + Thread.CurrentThread.GetHashCode().ToString());
string strDSN = ConfigurationManager.ConnectionStrings["DSN"].ConnectionString + ";async=true";
string strSQL = "waitfor delay '00:00:10'; select * from TEProcessedPerDay where Date > dateadd(day, -90, getutcdate()) order by Date asc";
m_oConnection = new SqlConnection(strDSN);
m_oCommand = new SqlCommand(strSQL, m_oConnection);
m_oConnection.Open();
Page.RegisterAsyncTask(new PageAsyncTask(new BeginEventHandler(BeginHandler), new EndEventHandler(EndHandler), new EndEventHandler(TimeoutHandler), null, true));
}
IAsyncResult BeginHandler(object src, EventArgs e, AsyncCallback cb, object state)
{
Trace.Warn(ID, "BeginHandler - " + Thread.CurrentThread.GetHashCode().ToString());
return m_oCommand.BeginExecuteReader(cb, state);
}
void EndHandler(IAsyncResult ar)
{
Trace.Warn(ID, "EndHandler - " + Thread.CurrentThread.GetHashCode().ToString());
GridView1.DataSource = m_oCommand.EndExecuteReader(ar);
GridView1.DataBind();
m_oConnection.Close();
}
void TimeoutHandler(IAsyncResult ar)
{
Trace.Warn(ID, "TimeoutHandler - " + Thread.CurrentThread.GetHashCode().ToString());
}
</script>
<asp:gridview id="GridView1" runat="server" />
And the unchanged page that creates three instances of the control:
<%# page language="C#" async="true" trace="true" %>
<%# register tagprefix="uc" tagname="mycontrol" src="~/MyControl.ascx" %>
<html>
<body>
<form id="form1" runat="server">
<uc:mycontrol id="MyControl1" runat="server" />
<uc:mycontrol id="MyControl2" runat="server" />
<uc:mycontrol id="MyControl3" runat="server" />
</form>
</body>
</html>
If I may add a little to the above post, we should not call the ExecuteRegisteredAsyncTassk explicitly unless there is a compelling reason. once you register the async task, the ASP.NET framework will execute all these tasks right after the OnPrerender event of the page lifecycle.
An example for the usage of ExecuteRegisteredAsyncTasks could be;
Sometimes you may need to ensure that several async operations are completed before calling another async task. in a situation like this it is justifiable to use ExecuteRegisteredAsyncTasks.