Problem with Session unpack - asp.net

I have some problems with this code:
private void BoxVisibility(bool email, bool link, Control linkButton)
{
mainEmail.Visible = email;
foreach (Control c in PlaceHolder1.Controls)
{
c.Visible = false;
}
if (linkButton != null)
{
PlaceHolder1.Visible = true;
linkButton.Visible = link;
}
}
when I send to method Control all is ok, but when at first I put Control in Session['temp'] = Control, and then invoke the method like BoxVisibility(false, true, (Control) this.Session['temp']) in this case Control linkButton.Visible = link; doesn't take true, He's still remain false.

The "control" is a reference to a particular instance for this particular page.
The Page is recreated on every request, so a reference to an old instance of your control is no longer valid. So don't store controls in anything (Session, ViewState, static fields) that lives longer than the single request. Local (instance) fields of your page are safe.

Related

MessagingCenter.Subscribe in not listening to outsider messages?

I'm loading the page's data in the OnAppearing method, but this causes loading data in situations where it doesn't change, like calling PopupAsync() from another page. so I thought the messaging center would help. I made a flag field in the page, and subscribed to any message coming from outside to decide whether to update data or not,
for example this from the MenuViewModel (when the user first opens the page, so I need to load data):
var p = new FeedbackListPage();
MessagingCenter.Send(this, "loadData", "1");
await Navigation.PushAsync(p);
and in the FeedbackListPage's constructor:
InitializeComponent();
BindingContext = vm = new FeedbackViewModel(Navigation);
MessagingCenter.Subscribe<string>(this, "loadData", ( _loadData) =>
{
loadDataStr = _loadData;
});
and in the OnAppearing:
protected override void OnAppearing()
{
base.OnAppearing();
if (loadDataStr=="1")
vm.OnLoadFeedbacks();
}
the problem is that the Subscribe's action is never called!
Solution:
The API for MessagingCenter:
1.Subscribe<TSender> (object subscriber, string message, Action<TSender> callback, TSender source = null)
2.Subscribe<TSender, TArgs> (object subscriber, string message,Action<TSender, TArgs> callback, TSender source = null)
So, if you want to pass an Argument using MessageCenter, you should define both Sender and Args:
MessagingCenter.Subscribe<MainPage,string>(this, "loadData", (sender,_loadData) =>
{
loadDataStr = _loadData;
});
Refer: messaging-center
You can try the following:
use MessagingCenter.Send to send the signal when you want to update the data from any page and then in your ViewModel's constructor use MessagingCenter.Subscribe to perform the needed action
Send:
MessagingCenter.Send<namespace.App>((namespace.App)Xamarin.Forms.Application.Current, "update");
Subscribe:
MessagingCenter.Subscribe<namespace.App>((namespace.App)Application.Current, "update", (sender) => {
// update - get data
});

Trying to set RadTreeView node checked status programatically from persistence

There must be something I'm missing here. I have two instances of RadTreeView, for which I store node check data in a cookie. Upon page load, I then want to read this cookie, and set checked status accordingly.
So I have this OnDataBound event:
protected void RadTreeView1_OnDataBound(object sender, EventArgs e)
{
HttpCookie checkedCookie = Request.Cookies[DataType + "Checked"];
if (checkedCookie != null)
{
var cookieValue = checkedCookie.Values["Checked"];
if (cookieValue != null)
{
var checkedNodeValues = cookieValue.Split('*');
foreach (string nodeValue in checkedNodeValues)
{
RadTreeNode checkedNode = RadTreeView1.FindNodeByValue(HttpUtility.UrlDecode(nodeValue));
if (checkedNode != null)
checkedNode.Checked = true;
}
}
}
}
And in the foreach loop, I find a corresponding node for every cookie value. What's more is, their initial Checked status is false.
So why are all other nodes also getting checked?
Try using the RadPersistenceFramework. Adding a single entry for your treeview to the PersistenceManager (or PersistenceManagerProxy) control should let you store the checked state. You can see this here http://demos.telerik.com/aspnet-ajax/treeview/examples/applicationscenarios/persisting-treeview-settings/defaultcs.aspx?product=persistenceframework
Of course, storing the data depends a bit on your case (you can have a custom provider and still keep the data in a cookie, or you can keep things in a database, whatever works for you: http://demos.telerik.com/aspnet-ajax/persistence-framework/examples/custom-storage-provider/defaultcs.aspx).

ASP.NET NullReferenceException

I am trying to write the user login details to the Database.
When I click the submit button Im getting a NullReferenceException.
There are 4 TextBoxes
Username, Email, Password and ConfirmPassword.
protected void Button1_Click(object sender, EventArgs e)
{
if ((RegisterUserWizardStep.FindControl("Password") as TextBox).Text == (RegisterUserWizardStep.FindControl("ConfirmPassword") as TextBox).Text)
{
//call the method to execute insert to the database
ExecuteInsert((RegisterUserWizardStep.FindControl("UserName") as TextBox).Text,
(RegisterUserWizardStep.FindControl("Email") as TextBox).Text,
(RegisterUserWizardStep.FindControl("Password") as TextBox).Text);
Response.Write("Record was successfully added!");
ClearControls(Page);
}
else
{
Response.Write("Password did not match");
(RegisterUserWizardStep.FindControl("Password") as TextBox).Focus();
}
}
Thank you.
You mention there are four controls - Username, Email, Password and ConfirmPassword
The null exception you are seeing is almost certainly because FindControl(X) is returning null
A better way of checking is to do something like:
TextBox myTextBox = RegisterUserWizardStep.FindControl(X) as TextBox;
if(myTextBox != null){
//Continue
}
else{
//Write out some error information - now you know what the problem is.
}
Further, and this isn't related to your immediate error, but then you feed the contents of each of the text boxes directly into your ExecuteInsert method - you'd be better off doing some validation, too, just to check you have expected values.
Its likely that FindControl didn't find the control you are after, possibly because the TextBoxes are nested under another child control like a panel etc.
Instead of
if ((RegisterUserWizardStep.FindControl("Password") as TextBox).Text
try
TextBox passwordTextBox = RegisterUserWizardStep.FindControl("Password") as TextBox;
// .. same for username and email
if ((passwordTextBox != null) && (usernameTextBox != null) ... )
{
// Do something with the textboxes
}
// else you have a bug
This will also prevent you repeating the FindControl code on the same control (DRY principle)
In your description you've said that you have a Username TextBox.
The code is looking for RegisterUserWizardStep.FindControl("UserName").
Is this a typo in the question? otherwise it could be the cause of the exception.
Code like RegisterUserWizardStep.FindControl("UserName") as TextBox will return null either if there is no control named UserName or if the control named UserName can't be cast to a TextBox. This is most likely the source of your exception because you attempt to get the property Text of a reference that might be null.
To better understand where the problem is you can define an extension function:
static class ControlExtensions {
public T Find(this Control parent, String name) where T : Control {
var control = parent.FindControl(name);
if (control == null)
throw new ArgumentException(String.Format("Cannot find control named '{0}'.", name);
var t = control as T;
if (t == null)
throw new ArgumentException(String.Format("Control named '{0}' does not have type '{1}.", name, typeof(T).Name);
return t;
}
}
You can then get the Text property of the UserName control:
RegisterUserWizardStep.Find<TextBox>("UserName").Text
This call will throw a more descriptive exception if the control isn't found.

Output Caching using BOTH varybyparam and varybycustom

I'm trying to do something which should be very simple...I have a site with a dropdown from which the user selects a group. Thereafter, the user navigates through the site using querystring arguments from menus. So I want the caching to be dependent on the querystring - this seems to work. I also want the cache to be dependent on the group that they selected.
But when the querystring is empty, neither cache element seems to work - the page is just whatever the version was for the last selected group. My cache directive looks like this:
<%# OutputCache Duration="300" VaryByCustom="currentAtomId" VaryByParam="documentId;folderId;sectionId;renderMode;typeId" %>
My varyByCustom code looks like this:
public override string GetVaryByCustomString(HttpContext context, string custom)
{
switch (custom)
{
case "currentAtomId":
var currentAtomId = SecurityManifold.Create().CurrentAtomId;
var returnString = currentAtomId == null ? Guid.NewGuid().ToString() : currentAtomId.ToString();
return returnString;
default:
throw new ArgumentException(string.Format("Argument '{0}' is not a valid cache argument.", custom));
}
}
The call to CurrentAtomId boils down to this:
public static int? GetCurrentAtomIdFromContext(HttpContext context)
{
int entityId;
if (context.Session == null)
{
throw new InvalidOperationException("Session is null");
}
var sessionEntityId = context.Session["CurrentEntityId"];
if (sessionEntityId == null || string.IsNullOrEmpty(sessionEntityId.ToString()))
{
return null;
}
if (!int.TryParse(sessionEntityId.ToString(), out entityId))
{
return null;
}
return entityId;
}
Finally, the code which specifies the CurrentEntityId is this:
var selectedEntityId = this.lstSecurityEntities.SelectedValue;
if (string.IsNullOrEmpty(selectedEntityId))
{
return;
}
Session["CurrentEntityId"] = selectedEntityId;
var possibleQueryString = Request.QueryString.ToString();
if (!string.IsNullOrEmpty(possibleQueryString))
{
possibleQueryString = "?" + possibleQueryString;
}
Response.Redirect("default.aspx" + possibleQueryString);
I'm baffled. Any thoughts would be appreciated.
I eventually determined the problem - when output caching is placed at a PAGE level (as opposed to a control level), the session is not available, and throws an exception. Because this exception is occurring in Global ABOVE the global error handler, it fails silently. I eventually figured this out by wrapping a try-catch block around the cache key generation code in VaryByCustomString and Response.Write-ing it out.
What a beatdown...at any rate, the solution is to implement caching at the control level, which unfortunately is a lot more work because the pieces of the page work together...but it's better than no caching. I hope this helps save somebody else some time.
Bottom Line: for varyByCustomString in global.asax - SESSION IS NOT AVAILABLE WHEN CACHING AT THE PAGE LEVEL.

ASP.NET private member field loses value on postback

Consider the following code:
public partial class TeacherControlPanel : System.Web.UI.Page
{
protected string username = string.Empty;
protected void Page_Load(object sender, EventArgs e)
{
username = (string)Request.QueryString["username"];
Ice_Web_Portal.BO.Teacher teacher = Ice_Web_Portal.BO.Teacher.GetTeacherByUsername(username);
if (teacher != null)
{
labUsername.Text = username;
labName.Text = teacher.TeacherName;
labTeacherCode.Text = teacher.TeacherCode;
Dept dept = teacher.Department;
if (dept != null)
{
labDepartment.Text = dept.DeptName;
}
}
else
{
//labErrorMessage.Text = "No teacher found";
}
}
protected void btnSendMail_Click(object sender, EventArgs e)
{
Response.Redirect(#"~/Teacher/TeacherComposeMail.aspx?username=mahabub" + username);
}
}
In this code, when I am declaring 'username' as private, it is initialized to null after subsequent post backs.
Why?
What is the secret?
Because ASP.NET is stateless meaning it does not keep it state from post back to postback. Save the user to the viewstate, session, or application to see it on postback to postback.
#region UserName
public string UserName
{
get
{
if (this.ViewState["UserName"] == null)
return string.Empty;
return (string)this.ViewState["UserName"];
}
set { this.ViewState["UserName"] = value; }
}
#endregion
Every time you do any postback, even for "simple" things like button click events, you're working with a new instance of the page class. That's ASP.Net 101.
Declaring the username field as private or protected has no bearing on this situation. The only bearing protected/private would have is the accessibility of the variable outside the class or in inherited members.
I believe this is likely a lifecycle problem.
When you navigate to this page for the first time, user name will only have a value if the query string was set for the request. So, "/TeacherControlPanel.aspx" will have a user name with no value, but "/TeacherControlPanel.aspx?username=SomeUserName". In these cases, the field username is only going to have a value if one is set. And if no querystring is set, then when the page processes the button click event, the load will fire, no query string set means that username will be null, which means that the click event will have nothing to append to the redirect string.
So the question is, in your application, what navigation path are you using to get to TeacherControlPanel.aspx?

Resources