ASP.Net aspx properties persisted - asp.net

What would be the best practice to persist property values of an aspx-page?
I have done the following, is there some neater way?
public string DataTable
{
get
{
return _DataTable;
}
set
{
_DataTable = value;
ViewState["DataTable"] = value;
}
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DataTable = Request["dataTable"].ToString();
}
else
{
DataTable = ViewState["DataTable"].ToString();
}
}

You have multiple places where you can persist data,each with it's own pros and cons, and with it' own lifespan:
ViewState - stored individually on each page as a hidden (somewhat encrypted) item on the client. Remember that the data has to make a round trip to the client and back on each postback, so generally it's not a good ideea to store large ammounts of data
HiddenItem - a hidden input control. Works the same as ViewState, except it's not enrypted and you can use the values in the JS from the client
QueryString - same as hiddenitem, but seriously, use it only for small ammounts of data. I think some browsers have a limit on the URL length
Session - has the advantage of being able to store larger ammounts of data, as this is stored on the server end, not on the client. You can get into trouble if the client is using the back/next buttons on the browser, and you need to be carefull about maintaining session data accross server farms(ie. multiple servers running the same webapp)
Cache - almost identical to Session, except you can access it from other sessions. This is better to use for "globally" accesable data (ie. stuff everyone uses in you app)
Static Properties - works the same as cache, but you cannot share it across webfarms, so each member of the webfarm will have it's own static value in it's loaded assembly.

I would do it like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
TableName = Request.QueryString["tableName"];
}
public string TableName
{
get { return ViewState["tableName"] as string; }
set { ViewState["tableName"] = value; }
}
I don't like using Request["tableName"] alone since it has to search in more places. Usually I know where I'm sending the parameter.
Also DataTable is a type, so it's best to not use it as a property name.

Related

How to pass multiple parameters to a crystal report?

I have a crystal report in my asp.net web application which has a lot of report parameters (about 15). Previously I was using querystring to pass them but it was being unsecure.
Now I am mapping all parameters to a Hashtable, storing them in session & passing to the report viewer. Now If user opens multiple instance of reports in different browser tabs, the session values get messed up. When I navigate pages, wrong reports are displayed.
Please advise me a good method to pass my parameters to report.
Damien.
How about creating a simple DTO for storing all report parameters. Save this DTO in session and access in report viewer page where your viewer control resides.
To cross over the session issue when user opens multiple instances in browser, you can do a simple trick. When user provides parameter, and clicks on "Show Report", at that point create a guid, store value inside the session using key as this guid, and pass this guid as query string parameter to your report viewer page. This way each instance of report viewer page is aware which session value to be brought out.
Something like this
public class AttendanceDTO
{
public int EmployeeId {get;set;}
public string Month {get;set;}
}
And then in your "Report parameter page"
/* JUST NOTEPAD CODE, SYNTAX MIGHT VARY */
protected override ShowReport_Click(object sender, EventArgs e)
{
string guid = new Guid();
AttendanceDTO dto = new AttendanceDTO()
{ EmployeeId = txtEmployee.Text;
Month = txtMonth.text
};
session[guid] = dto;
Response.Redirect("ReportViewer.aspx?Guid=" + guid);
}
And then inside your Report Viewer Page
string guid = Request.QueryString["Guid"]; //Null check etc..
AttendanceDTO dto = (AttendanceDTO) session[guid];
//Provide dto values as parameters to your report viewer control and then clean the session
[You would need to make sure that you clear out the respective session value after you get it used.]
[Above code is just from notepad to give you an idea. On top of this you can bring more innovation]
Session Objects are shared among multiple tabs of same browser since server stores only one session cookie for a browser. So it is pretty obvious for the values to messup in several tabs on single browser.
One of the possible solution:
Use ViewStates instead of session to store HashTable.
Refer the code below for a demo, I have used ArrayList instead is HashTable for the sake of simplicity.
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
ViewState["ht"] = new ArrayList();
//initialize viewstate with arraylist on first pageload.
}
}
protected void btnAddElement_Click(object sender, EventArgs e)
{//adding new elements to the arraylist
if (ViewState["ht"] != null)
{
ArrayList ht = (ArrayList)ViewState["ht"];
ht.Add(TextBox1.Text);
ViewState["ht"] = ht;
}
}
protected void Button2_Click(object sender, EventArgs e)
{
if (ViewState["ht"] != null)
{
ArrayList ht=(ArrayList)ViewState["ht"];
foreach (object a in ht)
{//write code to pass parameters to the crystal report
Response.Write(a);
}
}
}
}
Since Viewstates work at page level, therefor the values in the collection will not mess up this time.
Hope this helps.

asp.net set sessions before postback

is there an easy way, to store all needed global variables in sessions at once, before the PostBack starts? Or have I to store them in each step where I change them?
I will do something like:
// Global variable.
bool test = true;
// Store all needed information in a session.
protected void Before_globalvariable_is_set_to_default_value(...)
{
Session["Test"] = test;
...
}
protected void Page_Load(object sender, EventArgs e)
{
if(IsPostBack)
{
//if(Session["Test"] != null)
//{
test = (bool)Session["Test"];
Session.Contents.Remove("Test");
//}
}
}
Is something like that possible?
Additional Information
At the Page_Load (!IsPostBack) I check if the user gets more vision, if he gets, I set a global var to true. Later in my code I check if that var is true and add additional columns to a GridView.
Now if a PostBack occurs, I can’t check that var, because I lose the information. I knew that I need to store the information in a Session. If I set the Session at the time where I set the global var to true, I get problems with the session timeout (If the user is on the site, but doesn’t do something for a while). So I thought it will be good, if I set the Session shortly before I lose the information of the global var and delete the Session after reinitialization.
That’s my idea, but I don’t know if something like that is possible.
Edit2:
If I do following it works:
//Global variable
bool test = false;
protected void Page_PreRender(object sender, EventArgs e)
{
Session["Test"] = test;
}
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
test = (bool)Session["Test"]; // Session is true!!!
Session.Contents.Remove("Test");
}
else
{
test = true; // Set at the PageLoad the var to true.
}
}
I’m a little bit confused, I thought PreRender is after the PageLoad, why suddenly the test var is true and if I remove the PreRender it isn’t?
Greetz
If you're worried about losing a specific value between requests, because you've maintained the state of that variable in the Session object and it might have been cleared by a timeout, you could consider using another, more durable, mechanism to save the state: for example, cookies or database.
If the value only needs to live during that one Request, you can use class-level fields of the code-behind class. Set them in the Init or Load phase, then you can use those values in all other phases.
For a lifetime of just a single request:
public partial class MyPage: Page
{
private bool test = true;
public void Page_Load(...)
{
// maybe set 'test' to another value
}
public void Button_Click(...)
{
// you can still access 'test'
}
public void Page_PreRender(...)
{
// you can still access 'test'
}
}
If however you need that value to live from request to the next postback, you can use ViewState instead of Session. Advantage: no timeout as it is stored in the html and posted back from the browser along with other data. Disadvantage: it only works in postback-scanario's, not when you link to a different page.

Avoid database round trips when we have more than one user control on aspx page

I have more than one user control on my aspx page, and each user control call it's own service or method to display content retrieved from SQL DB. I want to reduce these round trips, and get the job done in one call. Any idea what's the best practice.
You can put your all select statements in one stored procedure that mean you will hit your database just one time and load the result into a DataSet using SqlAdapter.Fill(MyDataSet) and pass the each table in your dataset to corresponding user control by creating public property with DataTable type
public class UserControl_1
{
private DataTable _dbTable;
public DataTable dbTable;
{
get
{
return _dbTable;
}
set
{
_dbTable = value
}
}
}
in your page
Private DataSet myDataSet;
public void Page_Load(Object sender,EventArgs e)
{
myDataSet = PopulateData(); // call your stored procedure inside it
UserControl_1.dbTable = myDataSet.Tables[0];
UserControl_2.dbTable = myDataSet.Tables[1];
//... and so on
}
I wish that give you a good idea

ASP.NET SqlServer Session State

I have configured an asp.NET web application to use forms authentication and store the session in a custom table. So far so good, when I log in the authentication persists across browser sessions. I am trying to get to grip with the possibilities of storing the session like so but I come up against a problem early on.
If I add variable/value pairs to the session object, and output the session variables to the page, the variable/value pairs are displayed as expected, but when I close and reopen the browser the correct session reloads as expected (which I confirm by outputting the sessionid) but the variable/value pairs are gone.
Is there something very simple I am missing here as from what I understand the session variables should also be available across browser sessions(strings are serializable right?).
List<SessionVar> sessionVars = new List<SessionVar>();
protected void Page_Load(object sender, EventArgs e)
{
Session[Session.SessionID] = Session.SessionID;
LoadSessionData();
}
protected void btnSessionVariable_Click(object sender, EventArgs e)
{
Session[txtVariableName.Text.Trim()] = txtVariableValue.Text.Trim();
txtVariableName.Text = string.Empty;
txtVariableValue.Text = string.Empty;
LoadSessionData();
}
private void LoadSessionData()
{
sessionVars.Clear();
foreach (string key in Session.Keys)
{
sessionVars.Add(new SessionVar(key, (string)Session[key]));
}
gridView.DataSource = sessionVars;
gridView.DataBind();
}
Session state is NOT maintained when a browser (or browser tab) closes and is restarted.
The session cookie is no longer available for the new browser window so a new session will start. That ASP.NET assigns the same id again is just a coincedence.

Redirecting users from edit page back to calling page

I am working on a project management web application. The user has a variety of ways to display a list of tasks. When viewing a list page, they click on task and are redirected to the task edit page.
Since they are coming from a variety of ways, I am just curious as to the best way to redirect the user back to the calling page. I have some ideas, but would like to get other developers input.
Would you store the calling url in session? as a cookie? I like the concept of using an object handle the redirection.
I would store the referring URL using the ViewState. Storing this outside the scope of the page (i.e. in the Session state or cookie) may cause problems if more than one browser window is open.
The example below validates that the page was called internally (i.e. not requested directly) and bounces back to the referring page after the user submits their response.
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (Request.UrlReferrer == null)
{
//Handle the case where the page is requested directly
throw new Exception("This page has been called without a referring page");
}
if (!IsPostBack)
{
ReturnUrl = Request.UrlReferrer.PathAndQuery;
}
}
public string ReturnUrl
{
get { return ViewState["returnUrl"].ToString(); }
set { ViewState["returnUrl"] = value; }
}
protected void btn_Click(object sender, EventArgs e)
{
//Do what you need to do to save the page
//...
//Go back to calling page
Response.Redirect(ReturnUrl, true);
}
}
This message my be tagged asp.net but I think it is a platform independent issue that pains all new web developers as they seek a 'clean' way to do this.
I think the two options in achieving this are:
A param in the url
A url stored in the session
I don't like the url method, it is a bit messy, and you have to remember to include the param in every relevent URL.
I'd just use an object with static methods for this. The object would wrap around the session item you use to store redirect URLS.
The methods would probably be as follows (all public static):
setRedirectUrl(string URL)
doRedirect(string defaultURL)
setRedirectUrl would be called in any action that produces links / forms which need to redirect to a given url. So say you had a projects view action that generates a list of projects, each with tasks that can be performed on them (e.g. delete, edit) you would call RedirectClass.setRedirectUrl("/project/view-all") in the code for this action.
Then lets say the user clicks delete, they need to be redirected to the view page after a delete action, so in the delete action you would call RedirectClass.setRedirectUrl("/project/view-all"). This method would look to see if the redirect variable was set in the session. If so redirect to that URL. If not, redirect to the default url (the string passed to the setRedirectUrl method).
I agree with "rmbarnes.myopenid.com" regarding this issue as being platform independent.
I would store the calling page URL in the QueryString or in a hidden field (for example in ViewState for ASP.NET). If you will store it outside of the page scope (such as Session, global variable - Application State and so on) then it will not be just overkill as Tom said but it will bring you trouble.
What kind of trouble? Trouble if the user has more than one tab (window) of that browser open. The tabs (or windows) of the same browser will probably share the same session and the redirection will not be the one expected and all the user will feel is that it is a bug.
My 2 eurocents..
I personally would store the required redirection info in an object and handle globally. I would avoid using a QueryString param or the like since they could try bouncing themselves back to a page they are not supposed to (possible security issue?). You could then create a static method to handle the redirection object, which could read the information and act accordingly. This encapsulates your redirection process within one page.
Using an object also means you can later extend it if required (such as adding return messages and other info).
For example (this is a 2 minute rough guideline BTW!):
public partial class _Default : System.Web.UI.Page
{
void Redirect(string url, string messsage)
{
RedirectionParams paras = new RedirectionParams(url, messsage);
RedirectionHandler(paras); // pass to some global method (or this could BE the global method)
}
protected void Button1_Click(object sender, EventArgs e)
{
Redirect("mypage.aspx", "you have been redirected");
}
}
public class RedirectionParams
{
private string _url;
public string URL
{
get { return _url; }
set { _url = value; }
}
private string _message;
public string Message
{
get { return _message; }
set { _message = value; }
}
public RedirectionParams(string url, string message)
{
this.URL = url;
this.Message = message;
}
}

Resources