I am generating some head html in page load and because of that I query database once. in the page I query database again and put data into html with inline code.
my question is is there better way to do this? I dont want to query database everytime and reach out those filled variables from inline code. something like page.addVariable in page_load and reach those at inline like page.variables["variablename"]
thanks in advance
If I understand what you are asking, you can make an accessor and set it to Protected. That will allow you to access it from the page.
If you want to prevent calling the database on callbacks, you could always add the information to the view state on the page.
Information on the view state, hidden fields, and cookies:
http://www.csharphelp.com/archives/archive207.html
I'm not sure if this is what you're after, but you can use a HiddenField to store any data you want on the page.
Also, if you don't need it to be on the page, you can use Session or ViewState.
Here's an example of using ViewState as a property (NB. you can interchange ViewState with Session, look at the links I gave you for an explanation between the two):
public string YourProperty
{
get
{
object content = ViewState["YourProperty"];
if (content == null)
{
return string.Empty;
}
return content.ToString();
}
set
{
ViewState["YourProperty"] = value;
}
}
Note, that anything you put into ViewState or SessionState must be marked as Serializable.
If it's quite a simple class, just mark the class with the [Serializable] tag.
Is the data you retrieve from the database page specific, user specific or global to the entire application?
If the data is user specific you can use Session State.
If the data is global to the entire application you could use Application State.
Whichever you use, you can implement the data retrieval in the Session_Start (will be called only once for each user) or Application_Start (will be called only once when the web app starts) events in a Global.asax file.
Related
Ok. Here we go. I am not sure if anyone here has implemented this, but I have a user control in my Webforms application which I am calling on several forms.
This user control has a dropdown which calls the stored procedure and filters the dropdown according to a certain date. However, on one of the forms, I want same user control to still call the stored procedure but not filter at all, just fetch all records.
Basically, I want same user control to do one thing on one form and another thing on another form. I want to use same user control since there is only small change. Rest is the same and hence I want to avoid creating another form.
Is this possible?
Thank you.
The easiest way is create a property on the user control:
public bool SOmeCOnfigurableSetting
{
get { return ((bool?)ViewState[".."]).GetValueOrDefault(false); }
set { ViewState[".."] = value; }
}
It can be any type, not just bool. In each page, set the property on the user control definition, and this controls the filtering or other functionality.
I have a dynamic ASP.NET form which I recreate evertime I postback. My values persist no problem.
I am however having a challenge maintaining attributes on Postback. For example, I have user defined code which may enable or disable a field when someone is first presented with the form. If a user posts the form I need an easy way to make sure the field stays enabled or disabled.
Does this make sense? Is there an easy way to do this?
ViewState is the preferred method of persisting information between postbacks that doesn't need to live beyond the scope of a single page. You can store information pretty easily there.
An easy way to accomplish this is to use a property in the control, or the page that abstracts the use of ViewState from you.
protected Boolean IsFieldVisible
{
get{ return (Boolean)ViewState["SomeUniqueKey"] ?? false; }
set{ ViewState["SomeUniqueKey"] = value; }
}
This will maintain the value between postbacks.
I stored a object in viewstate on Page. Now when i access the same viewsate object on usercontrol,it shows as null. I even tried creating the same viewstate with same name in usercontrol and page.Both holds different value.
I understand that viewstate is a protected property. How does this thing implement in above scenerio or is there any other reason for this behaviour.
Edit:
Usercontrol is there in the page markup. I am not loading it dynamically.
I have a page EditFacilityworkType.aspx. On page I have a usercontrol FacilityWorkTypeDetails.aspx(FacilityWorkTypeDetails1). Inside this usercontrol i have a user control Workflow.aspx(Workflow1)
Page_Load() of Page
I am retrieving workflowdetails on page_load() of page.
FacilityWorktype facilityWorkType = facilityDetails.GetFacilityWorktypeDetail(SessionHelper.FacilityWorkTypeID);
ViewState["WorkFlow"] = facilityWorkType.FacilityWorkTypeWorkFlow
Inside usercontrol FacilityWorkTypeDetails.aspx. I have a property
public FacilityWorktype FacilityWorkTypeDetails
{
get
{
#region Fill FacilityWorktype
return GetEntityFromControl();
#endregion
}
set
{
PopulateControls(value);
}
}
Now i set this property in page load of page
FacilityWorkTypeDetails1.FacilityWorkTypeDetails = facilityWorkType;
Inside Workflow.aspx, I have a property
/// <summary>
/// Property to fill entity object from controls on this page
/// </summary>
public WorkFlow WorkFlowDetails
{
get
{
return GetEntityFromControls();
}
set
{
BindTranscriptionMethodDDL(ddlTranscMethod);
PopulateControls(value);
}
}
Now PopulateControls() of FacilityWorkTypeDetails1, i am setting property of workflow1
private void PopulateControls(FacilityWorktype value)
{
Workflow1.WorkFlowDetails = value.FacilityWorkTypeWorkFlow;
}
Now when i am retrieving values from
private WorkFlow GetEntityFromControls()
{
WorkFlow workFlow = (ViewState["WorkFlow"] as WorkFlow) ?? new WorkFlow();
//workFlow is null
}
So now inside this function workFlow is null. I want to ask,why is it null when i have set viewstate in page.
Scherand is very correct here. I'd like to add to what he has brought to the table.
Every control that derives from System.Web.UI.Control has the ViewState property. Under-the-hood the property is a StateBag collection. Every instance of a Control has its own StateBag for ViewState, so as Scherand mentioned, ViewState is unique to the control. When the page gets rendered, the entire Control tree of the Page is iterated, all ViewState collections are merged into a tree-like structure and that final structure is serialized to a string and rendered to the page.
Because the ViewState property is marked as protected, you can't get to the Page's ViewState from your User Control without the use of reflection.
But, in all honesty, you should abandon the use of ViewState as a data storage medium. Here are some reasons why:
ViewState gets rendered and output to the client browser. Maintaining data objects in the collection bloats your Page's output.
Unless you have encryption enabled on your ViewState, the encoded string that is rendered to the client browser can be decoded manually and simply anyone can access the content of your data objects. This is a rather significant security vulnerability.
It really sounds like all you want to do is share data between your Page and User Controls. The best way to share data between controls is to make use of the "Items" collection (which is a property of the HttpContext class). The collection is a Hashtable and can be accessed from your Page and User Controls like so:
Context.Items["Workflow"] = workflowInstance;
The best part of using this technique is that it doesn't incur any additional overhead or bloat the Page output. The Items collection exists in the context of a single HTTP request. This means that when your request is done and your Page's output has been rendered to the client browser, the Items collection is cleared from server memory. It's the ideal medium for temporary data storage within ASP.NET.
Now, if you want your data objects to remain accessible for more than just the current request, you'd be better off storing the objects in Session.
I still do not grok everything here (see my comments above). But I am pretty sure you are misunderstanding ViewState.
ViewState is per control, not per request or session or whatever.
In your example, consider some other control (e.g. a standard ASP.NET control) that for some reason decided to put something with a "name" of WorkFlow into viewstate. If what you are trying to do would work, this object would overwrite yours (or the other way around, yours would be overwritten by the other one).
Or am I missing something?
Maybe reading TRULY Understanding ViewState could help you understand what viewstate is/how it works (yes, I really like this article, this is why I keep posting that link).
On postback did you create the control? If the code behind hasn't created the ctrl then it won't know about it.
only applicable if this is a generated control. You may need to post code and more info to get a propper answer.
Viewstate is a monster which is why a lot of us are going to MVC.
the page viewstate is a different statebag from the viewstate that the usercontrol can access. each control has their own private viewstate. So you cannot directly access the page viewstate from a usercontrol code-behind.
you could expose viewstate values with properties or methods and then call those properties/methods
I have some control. I add one instance of this control to every Page in OnInit event and I want to access this control in other places in this way: Sample.Current
public class Sample : Control
{
public static Sample Current
{
get
{
// ???
}
}
}
Can you tell me what is the best way to do this property implementation?
It would be good to have a bit more detail - what is this class' purpose? But I'll attempt to help anyway:
You'll be able to access that control from within code on the page , if it's referenced in the code and not added dynamically somehow at runtime. ie if it's a variable of the page declared like:
Sample ctrl = new Sample();
Then later you can reference it using ctrl.Current in your code.
FYI - if you want a place to reference classes and variables for a page's lifecycle, you may want to check out HttpContext.Current.Items http://www.mikeduncan.com/3-hot-uses-for-httpcontextcurrentitems-they-wont-tell-you-about/ It's like a session bag that only exists for a single page request - for example if you have a class that holds information about a user that you need to access many times from many different controls on the page, you could just stick that class into the Items collection and then reference it from any code that runs on your page.
HTH,
Lance
So, I've got an ASP drop down list (this is .net 2.0). I'm binding it with data. Basically, when the page loads and it's not a post back we'll fetch record data, bind all the drop downs, and set them to their appropriate values (strictly speaking we: initialize page with basic set of data from DB, bind drop downs from DB, fetch actual record data from DB, set drown downs to appropriate settings at this time). What I want to do is selectively style the list options. So the database returns 3 items: ID, Text, and a flag indicating whether I the record is "active" (and I'll style appropriately). It's easy enough to do and I've done it.
My problem is what happens when a form submission is halted. We have slightly extended the Page class and created an AddError() method, which will create a list of errors from failed business rule checks and then display them in a ValidationSummary. It works something like this, in the submit button's click event:
CheckBizRules();
if(Page.IsValid)
{
SaveData();
}
If any business rule check fails, the Page will not be valid. The problem is, when the page re-renders (viewsate is enabled, but no data is rebound) my beautiful conditional styling is now sadly gone, off to live in the land of the missing socks. I need to preserve it.
I was hoping to avoid another DB call here (e.g. getting the list data back from the DB again if the page isn't valid, just for purposes of re-styling the list). But it's not the end of the world if that's my course of action. I was hoping someone might have an alternative suggestion.
I couldn't think of how to phrase this question better, if anyone has any suggestions or needs clarification don't hesitate to get it, by force if need be. ;)
I'm not sure I completelly understand what kind of styling you apply to your drop-down items, but it seems this style is something that the control does not preserve accross postbacks. Usually this kind of info will therefore need to be saved in the ViewState.
I see two options (other than re-loading from DB):
First method: Create your own drop-down control that inherits from DropDownList. Then save styling data in the control's ViewState bag when styling the items:
public void SetItemActive(ListItem item)
{
ViewState[item.Value] = "active";
}
then override the OnRender
protected override void Render(HtmlTextWriter writer)
{
....
foreach(ListItem item in Items)
{
if ( ViewState[item.Value] == "active")
{
** RenderActiveItem **
}
else
{
** RenderNormalItem **
}
}
Second method: is to save the active ID's in the Page's ViewState then re-style the dropdown on each postback using the data from the ViewState rather than from the DB
Well, I couldn't come up with anything except to go to the database to re-retrieve my list data when the Page was not valid, and re-style the control.