ASP.NET/C# Where should I declare the Session using Property? - asp.net

NET Experts,
I got an ASP.NET MVP (Model View Presenter) application, where I am using GenMaster.Master (Master Page), Metadata.aspx (Start Page), Global.asax etc.
I am accessing the Session["EncryptedQuery"] in both GenMaster.Master (Master Page) and Metadata.aspx (Start Page).
Our Session declaration convention is to use property as follows:
public string EncryptedQuery
{
get
{
object SessionObject = Session["EncryptedQuery"];
return (SessionObject == null) ? String.Empty : (string)SessionObject;
}
set
{
Session["EncryptedQuery"] = value;
}
}
Now, where should I declare this Session property to access it in Master as well as all the content pages? And I do not want to assign/retrive to/from Session["EncryptedQuery"] direcly.
Thanks

A MasterPage is implemented as a Child Control of your Page. You should be able to access it using Page.Session from the MasterPage.
I just noticed you may have been asking is where to assign the property, rather than where to declare it. So, if you're asking what is the best practice as far as where to initialize Session data, then the answer is going to be the PostAcquireRequestState event of the HttpApplication class. You can declare this in either your Global.asax, or wire it up with a custom HTTP module.

This sort of strategy works well and allows for session data access from anywhere in the site in a strongly typed manner.
public static class SessionData
{
private const string ENCRPYTED_QUERY = "ENCRPYTED_QUERY";
public static string EncrpytedQuery
{
get
{
if (HttpContext.Current.Session != null)
return HttpContext.Current.Session[ENCRPYTED_QUERY] as string;
return null;
}
set
{
HttpContext.Current.Session[ENCRPYTED_QUERY] = value;
}
}
//add more down here...
}

Related

Access TextBox value of an ASP.NET page from C# class

Say there is a TextBox on an ASP.NET page
<asp:TextBox id="DateTextBox" runat="server" />
with some value set in the code-behind.
How to access that value from another class of C# code-file through HttpContext or any other way?
You can access a property in you page via HttpContext even from a static method.
in your page:
public string DateTextBoxText
{
get{ return this.DateTextBox.Text; }
set{ this.DateTextBox.Text = value; }
}
somewhere else(even in a different dll):
public class Data
{
public static string GetData()
{
TypeOfYourPage page = HttpContext.Current.Handler as TypeOfYourPage;
if (page != null)
{
return page.DateTextBoxText;
//btw, what a strange method!
}
return null;
}
}
Note that this works only if it's called from within a lifecycle of this page.
It's normally better to use ViewState or Session to maintain variables across postback. Or just use the property above directly when you have a reference to this page.
You can create a public property within the control that returns a reference to the textbox.
You can then use this property to reference the textbox.
OR
You can store in into session and then access it in your entire application.
Store it in the HttpContext Session http://www.codeproject.com/Articles/32545/Exploring-Session-in-ASP-Net
//Storing UserName in Session
Session["DateTextBox"] = DateTextBox.Text;
Now, let's see how we can retrieve values from session:
//Check weather session variable null or not
if (Session["DateTextBox"] != null)
{
// use it...
}
You could place the value in the Session during the post back. Then access it from the Session in the other class. So in your form load event write this:
Session["MyValue"] = DateTextBox.Text
and then in the other class write this:
var val = HttpContext.Current.Session["MyValue"];

Constructor in webform?

I have an ASP.NET webform where I initialize an array with a list of controls on the page like this
FileUpload[4] = new FileUpload[4];
public myclass()
{
fileUpload[0] = FileUpload1;
fileUpload[0] = FileUpload2;
...etc
}
I then use these in the page load and they are all null. This seems a strange behavior to me. Can someone elaborate and explain? I can understand that they are null in the constructor but why should they be null when used in the page load.
They are null because the controls haven't been created yet.
Take a look at the ASP.NET Page Life Cycle Overview and the Init event.
If you want to add controls "manually", you need to do this in OnInit() so they can be given state from the LoadViewState() call that will happen just after OnInit().
If you don't know how many controls you need to add, because it's dynamic somehow, you can override LoadViewState and SaveViewState. See this example(written without Visual Studio):
public class MyPage : Page
{
class State
{
numberOfControls int
otherState object
}
override void LoadViewState(savedState object)
{
var myState = (State)savedState;
SetupMyControls(myState.numberOfControls);
base.LoadViewState(myState.otherState);
}
override object SaveViewState()
{
return new State
{
numberOfControls = GetNumberOfMyControls(),
otherState = base.SaveViewState()
};
}
}

ASP.Net MVC: How do you access the session from a different project within the solution?

I have 2 projects in my solution.
MVC Web application
Class library
The MVC Web application references the class library.
The class library contains a class that extends the default ASP.Net Controller.
I'm putting a variable in session in the application's Global.asax.
protected void Session_Start(object sender, EventArgs args)
{
HttpContext.Current.Session["DomainName"] = Request.Url.Host;
}
In the class library I'm trying to get the value from the HttpContext.Session, but HttpContext.Session keeps coming up null.
public class MyController : System.Web.Mvc.Controller
{
public MyController () : base()
{
//HttpContext.Session is always null at this point
ViewData["DomainName"] = HttpContext.Session["DomainName"];
}
}
HttpContext.Current.Session doesn't seem to be an option in controllers. Any ideas?
Two issues -- the HttpContext property in the Controller class is the current session. Unfortunately, it's not available in the constructor of the controller. Obviously because it's not passed in the constructor, it has to be set via the property afterwards. You might consider adding a property to hold the domain name and referencing the session from it -- that way it would be available for use when needed.
protected string DomainName
{
get { return this.HttpContext.Session["DomainName"] as string; }
}
The set it in ViewData in your actions or in OnActionExecuting/OnActionExecuted.
protected override void OnActionExecuted( ActionExecutedContext context )
{
ViewData["DomainName"] = this.HttpContext.Session["DomainName"];
// or ViewData["DomainName"] = this.DomainName; // if you used the property
}
If you're just trying to add ViewData from the session, try doing it in the OnActionExecuting method. This is where I typically add ViewData I want for every View.
You just use Session by itself (it's a property of Controller), but that just maps to Controller.HttpContext.Session (in other words, what you're already using), so it won't solve your problem, which must be elsewhere.
I'm not sure why you're putting this in the Session, though, as you can read Request.Url.Host directly during the Action.
When you create cookie then you must write
Response.AppendCookie("Your cookie name");
And if you want to get that then something like this
if (Request.Cookies["Your cookie name"] != null)
{
string value = Request.Cookies["Your cookie name"].Value;
}
and must if there are different solutions
then
machineKey
need to be same which is under
system.web
in web.config and then write
<httpCookies domain=".yourdomainname.com" />

How to have a single "HelperClass.IsLoggedIn()" method for the entire ASP.NET web project?

This is a common need I have on every page:
if (session["LoggedIn"] == null || ((bool)session["LoggedIn"] != true))
....//user is not logged in. return.
I was wondering, is there a way I can create a class "Helper" with a method signature bool IsLoggedIn() and call that method from a page so that automatically it can check if the page it was called from has the session["LoggedIn"] set to true? Something like this:
class Helper
{
public bool IsLoggedIn()
{
System.Web.UI.Page page = ***FindCallerPageSomeHow***();
if(page.session["LoggedIn"] == null || ((bool)page.session["LoggedIn"] != true))
return false;
return ((bool)page.HpptContext.Session["LoggedIn"] == true);
}
}
Ofcourse, I could try implementing an interface for each codebehind class, but thats repetitive. Also, I could pass in the HttpContext for IsLoggedIn, but that's a bit of clutter..
Any ideas? Is there a simple-to-implement pattern for this?
If you want to use this approach I would probably add a extension method on the session. But using formsauthentication is usually a lot easier.
Update
Btw, here is the extension method:
public static bool IsSignedIn(this HttpSessionState session) {
//Use the session to check if the user is signed in
}
Then you can use it like this:
if(Page.Session.IsSignedIn()) {
//Code
}
You could always have a static class in a library somewhere, but my favorite technique is simply to create your own Page class and add properties or override events there.
public class myPage : System.Web.UI.Page
{
public void myPage()
{
}
public bool IsLoggedIn()
{
System.Web.UI.Page page = ***FindCallerPageSomeHow***();
if(page.session["LoggedIn"] == null || ((bool)page.session["LoggedIn"] != true))
return false;
return ((bool)page.HpptContext.Session["LoggedIn"] == true);
}
}
Then in the code behind of your actual page, you would have
public partial myAspxPage : myNamespace.myPage
{
}
As an example, my page class usually contains a public property called ValidUser that contains pertinent user information (so I don't have to keep looking it up). If that value is null, then I don't have one. If it's not, then I have what I need. Then whenever I create a new page in my site, I just have it inherit my page class instead of the default.
EDIT: Added your method in for a little more clarity.
Why not put the code in the master page? That way any pages that need to be tested for the user being logged in can inherit from that master page and all is handled automatically. Otherwise, you're just repeating yourself in the code for every page.
I would create a base class called BasePage which would inherit from System.Web.UI.Page. I would then have the codebehind class inherit from BasePage.
In BasePage, you just add a method called IsLoggedIn(), and you can call it from anywhere within your code behind class.

ASP.NET - Avoid hardcoding paths

I'm looking for a best practice solution that aims to reduce the amount of URLs that are hard-coded in an ASP.NET application.
For example, when viewing a product details screen, performing an edit on these details, and then submitting the changes, the user is redirected back to the product listing screen. Instead of coding the following:
Response.Redirect("~/products/list.aspx?category=books");
I would like to have a solution in place that allows me to do something like this:
Pages.GotoProductList("books");
where Pages is a member of the common base class.
I'm just spit-balling here, and would love to hear any other way in which anyone has managed their application redirects.
EDIT
I ended up creating the following solution: I already had a common base class, to which I added a Pages enum (thanks Mark), with each item having a System.ComponentModel.DescriptionAttribute attribute containing the page's URL:
public enum Pages
{
[Description("~/secure/default.aspx")]
Landing,
[Description("~/secure/modelling/default.aspx")]
ModellingHome,
[Description("~/secure/reports/default.aspx")]
ReportsHome,
[Description("~/error.aspx")]
Error
}
Then I created a few overloaded methods to handle different scenarios. I used reflection to get the URL of the page through it's Description attribute, and I pass query-string parameters as an anonymous type (also using reflection to add each property as a query-string parameter):
private string GetEnumDescription(Enum value)
{
Type type = value.GetType();
string name = Enum.GetName(type, value);
if (name != null)
{
FieldInfo field = type.GetField(name);
if (field != null)
{
DescriptionAttribute attr = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
if (attr != null)
return attr.Description;
}
}
return null;
}
protected string GetPageUrl(Enums.Pages target, object variables)
{
var sb = new StringBuilder();
sb.Append(UrlHelper.ResolveUrl(Helper.GetEnumDescription(target)));
if (variables != null)
{
sb.Append("?");
var properties = (variables.GetType()).GetProperties();
foreach (var property in properties)
sb.Append(string.Format("{0}={1}&", property.Name, property.GetValue(variables, null)));
}
return sb.ToString();
}
protected void GotoPage(Enums.Pages target, object variables, bool useTransfer)
{
if(useTransfer)
HttpContext.Current.Server.Transfer(GetPageUrl(target, variables));
else
HttpContext.Current.Response.Redirect(GetPageUrl(target, variables));
}
A typical call would then look like so:
GotoPage(Enums.Pages.Landing, new {id = 12, category = "books"});
Comments?
I'd suggest that you derive your own class ("MyPageClass") from the Page class and include this method there:
public class MyPageClass : Page
{
private const string productListPagePath = "~/products/list.aspx?category=";
protected void GotoProductList(string category)
{
Response.Redirect(productListPagePath + category);
}
}
Then, in your codebehind, make sure that your page derives from this class:
public partial class Default : MyPageClass
{
...
}
within that, you can redirect just by using:
GotoProductList("Books");
Now, this is a bit limited as is since you'll undoubtedly have a variety of other pages like the ProductList page. You could give each one of them its own method in your page class but this is kind of grody and not smoothly extensible.
I solve a problem kind of like this by keeping a db table with a page name/file name mapping in it (I'm calling external, dynamically added HTML files, not ASPX files so my needs are a bit different but I think the principles apply). Your call would then use either a string or, better yet, an enum to redirect:
protected void GoToPage(PageTypeEnum pgType, string category)
{
//Get the enum-to-page mapping from a table or a dictionary object stored in the Application space on startup
Response.Redirect(GetPageString(pgType) + category); // *something* like this
}
From your page your call would be: GoToPage(enumProductList, "Books");
The nice thing is that the call is to a function defined in an ancestor class (no need to pass around or create manager objects) and the path is pretty obvious (intellisense will limit your ranges if you use an enum).
Good luck!
You have a wealth of options availible, and they all start with creating a mapping dictionary, whereas you can reference a keyword to a hard URL. Whether you chose to store it in a configuration file or database lookup table, your options are endless.
You have a huge number of options available here. Database table or XML file are probably the most commonly used examples.
// Please note i have not included any error handling code.
public class RoutingHelper
{
private NameValueCollecton routes;
private void LoadRoutes()
{
//Get your routes from db or config file
routes = /* what ever your source is*/
}
public void RedirectToSection(string section)
{
if(routes == null) LoadRoutes();
Response.Redirect(routes[section]);
}
}
This is just sample code, and it can be implemented any way you wish. The main question you need to think about is where you want to store the mappings. A simple xml file could do it:
`<mappings>
<map name="Books" value="/products.aspx/section=books"/>
...
</mappings>`
and then just load that into your routes collection.
public class BasePage : Page
{
public virtual string GetVirtualUrl()
{
throw new NotImplementedException();
}
public void PageRedirect<T>() where T : BasePage, new()
{
T page = new T();
Response.Redirect(page.GetVirtualUrl());
}
}
public partial class SomePage1 : BasePage
{
protected void Page_Load()
{
// Redirect to SomePage2.aspx
PageRedirect<SomePage2>();
}
}
public partial class SomePage2 : BasePage
{
public override string GetVirtualUrl()
{
return "~/Folder/SomePage2.aspx";
}
}

Resources