I'm reading two values from the web.config in the Application_Start of my Global.asax.cs. The string values from the web.config are assigned to their public properties, also defined in the Global.asax.cs .
How do I access the properties in the global.asax.cs file from another class, method, and namespace?
Update #1
This is more complicated than I thought (or maybe I'm just making it complicated). The class where I want to reference these properties in a plain ol' class library and I don't have access to httpcontext (or I don't know how to access it).
Cast the current application instance to your Global type and access the properties there.
var app = (Your.App.Namespace.Global)HttpContext.Current.ApplicationInstance;
var x = app.YourProperty;
If the Global.asax.cs doesn't manipulate the values, then simply read the values from the web.config like you already do in global.asax.cs.
However, if the Global.asax.cs does manipulate the values, then you could write the values into the "Application" object.
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
Application.Add("Foo", "Bar");
}
Lastly, you can mark the property you want to expose from the Global as static.
public static string Abc { get; set; }
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
Abc = "123";
}
Related
I used forms authentication.
In LdapAuthentication.cs I have property
public static string ReturnProject
{
get
{
return HttpContext.Current.Session["Project"].ToString();
}
}
In global.asax.cs I trying to get Session["Project"] from LdapAuthentication.cs for check and ridirect to other pages according with rusult in Session["Project"], but I've got System.NullReferenceException. I cheked Session["Project"] in LdapAuthentication.cs - is ok
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
if (Request.AppRelativeCurrentExecutionFilePath == "~/")
{
if (LdapAuthentication.ReturnProject == "Team Leader")
HttpContext.Current.RewritePath("~/TLPage.aspx");
else
if (LdapAuthentication.ReturnName == "ccobserver")
HttpContext.Current.RewritePath("~/ScheduleReport.aspx");
else
HttpContext.Current.RewritePath("~/PersonPage.aspx");
}
}
doesn't matter which handler use Application_AcquireRequestState or Application_AuthenticateRequest.
Thanks!
You declared ReturnProject static property, while HttpContext is an instance property of HttpApplication class, implemented in Global.asax.
Static property has no access to instance properties, so removing static modifier from ReturnProject should fix the problem.
EDIT
Now I get it, ReturnProject property declared in LdapAuthentication.cs, not in Global.asax.
Let me explain a bit. Every time request hits a server, new instance of HttpApplication (hence, HttpContext instance property) is created. This way you get access to Request and Session — they are bound to concrete request associated with concrete user. Related answer: “HttpContext.Current.Session” vs Global.asax “this.Session”
What you seem trying to achieve is to pass some session variable (Project) to the LdapAuthentication class in a nice way. There are more than one way to do this, but the obvious way without looking to the source of LdapAuthentication class is to add LdapAuthentication instance field to the Global.asax, passing session variable through the constructor or property initializer. Something like this:
LdapAuthentication.cs
/// <summary>
/// Creates instance of LdapAuthentication with Project value initialized
/// </summary>
public LdapAuthentication(string project) {
this.ReturnProject = project;
}
Global.asax
private LdapAuthentication auth = new LdapAuthentication(
HttpContext.Current.Session["Project"].ToString()
);
...
protected void Application_AcquireRequestState(object sender, EventArgs e)
{
if (Request.AppRelativeCurrentExecutionFilePath == "~/")
{
if (auth.ReturnProject == "Team Leader")
HttpContext.Current.RewritePath("~/TLPage.aspx");
else
if (auth.ReturnName == "ccobserver")
HttpContext.Current.RewritePath("~/ScheduleReport.aspx");
else
HttpContext.Current.RewritePath("~/PersonPage.aspx");
}
}
How to use Application object in the web page?
I thought it should be something like Session object.
But when I use Application, it shows the Reference like
System.Net.Mime.MediaTypeNames.Application
Obviously, it's not the one I'm looking for.
Has it been discarded in .NET 4?
If yes, what should I use to replace the Application object.
Are you referring to this one
Page.Application Property
Gets the HttpApplicationState object for the current Web request.
<%
this.Application["test"] = "some value";
%>
inside a WebForm should work. And in the code behind it's the same story:
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
this.Application["test"] = "some value";
}
}
The Application (HttpApplicationState) property is very much there.
Seems you have some references that are causing the confusion.
In your CS code on a Page you should be able to use it
this.Application["key"] = myObject;
It should work if you try to access it from an ASP.NET page. Application is a property of Page that returns the HttpApplicationState.
protected void Page_Load(object sender, EventArgs e)
{
if(Page.Application["Foo"] != null)
{
// ...
}
}
If you want to access it from a static context, you can use HttpContext.Current:
if (HttpContext.Current.Application["Foo"] != null){ }
I am looking at a legacy enterprise application, which written using ASP.NET. No controls or web forms. This is how it works:
EmployeeList.aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="EmployeeList.aspx.cs" Inherits="EmployeeList" %>
EmployeeList.aspx.cs:
protected void Page_Load(object sender, EventArgs e)
{
// Security Check
// Load Template, get version 1.4 of active employee list
StringBuilder template = GetTemplate("Employee", "ActiveList", "1.4", true);
// Get list from database
using(SqlDataReader objReader = GetListFromDB())
{
while(objReader.Read())
{
//fills data
TUtils.Replace(template, ROW, "%name%", objReader[0]);
}
}
// return response
Response.Write(template.ToString());
}
private StringBuilder GetTemplate(string x, string y, string v, bool z);
{
// returns template
}
private SqlDataReader GetListFromDB() {
// returns data reader
}
My question is, since we are not using web forms, is there a way to introduce NUnit in this event driven model (as shown above)?
Also, please avoid suggestions to move to ASP.NET MVC or other patterns, which we are considering, but wondering is there any way to convert this enterprise application testable.
This is absolutely possible. You should have a look on implementing MVP pattern with ASP.NET Webforms. There are several open source implementations but you can do a smaller specialized on your your own.
The basics are to move your code behind logic to a presenterclass. The presenter class has a reference to the page implementing an interface. The trick in your case will be to Mock the Page.Response object for your test. Thats why it´s hard to unit test it right way. The PageResponse Property contains a object deriving from HttpResponseBase and that´s the baseclass you should Mock in your tests and do your asserts on with your example. You could start with that and then extend your presenter with functionalty like Session, Request etc.
If you don´t have any markup at all probably you can just create the presenter in the view constructor and don´t bother of having and reference to the view.
To clarify: The big trick is to get the code out of the aspx.cs file. That beast is not testable.
Sample base class for Presenters:
public class Presenter<T> where T : class, IView
{
protected readonly T View;
protected Presenter(T view, ILogger logger)
{
View = view;
}
public virtual void page_PreRender(object sender, EventArgs e)
{
}
public virtual void page_Init(object sender, EventArgs e)
{
}
public virtual void page_Load(object sender, EventArgs eventArgs)
{
}
public HttpContextBase HttpContext { protected get; set; }
protected HttpRequestBase Request
{
get { return HttpContext.Request; }
}
}
Since most of your code is in the code-behind, I dont think that the usual testing approach with NUnit / Visual Studio testing framework will work well.
However, I think one possible approach is to use UI Testing frameworks like WATIN / Selenium. This will enable you to still write tests for the various functionality.
I have done something similar in the past by basically writing a test case for every UI action that results in a server postback. May not be ideal but it does allow you to automate your testing.
I have this code
//file Globals.cs in App_Code folder
public class Globals
{
public static string labelText = "";
}
and a simple aspx page which has textbox, label and button. The CodeFile is:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = Globals.labelText;
}
protected void Button1_Click1(object sender, EventArgs e)
{
Globals.labelText = TextBox1.Text;
}
}
That is when I click on the button the Globals.labelText variable initializes from the textbox; the question is: why when I open this page in another browser the label has that value, which I set by the first browser, that is the static member is common for the every users. I thought that the every request provides in the individual appDomain which created by the individual copy of IIS process. WTF?
Yes you may use static variable to store application-wide data but it is not thread-safe. Use Application object with lock and unlock method instead of static variables.
Take a look at ASP.NET Application Life Cycle Overview for IIS 7.0 and ASP.NET Application Life Cycle Overview for IIS 5.0 and 6.0
No, static in this case is static in that manner only for the lifecycle of the process the request lives on. So this variable will be static the entire time you're processing a single request. In order to have a "static" variable in the manner you describe, you'd have to make it an application variable. Something like this:
//file Globals.cs in App_Code folder
public class Globals
{
// I really recommend using a more descriptive name
public static string LabelText
{
get
{
return Application("LabelText") ?? string.Empty;
}
set
{
Application("LabelText") = value;
}
}
}
By making it an application variable it should survive multiple page requests. A vulnerability it has though is that it will not survive an application pool recycle, and for large applications this can be problematic. If you truly want this variable to behave in a static manner reliably you're probably better off storing its state in a database somewhere.
I've a static page method in web form application and I want to call method on private class level variable from it as shown below. I'm using jQuery to call the page method.
private readonly ICatalogBLL _catalogBLL = new CatalogBLL();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
_catalogBLL.GetSomething();
}
}
[WebMethod]
public static UpdateSomething(int i)
{
//Want to do as below. But can't call it from a static method.
_catalogBLL.UpdateSomething();
}
UPDATE
If I call it as said by John Saunders, won't it use the same instance for requests from different users as it is within a static method?
You can't. The page method is static. Your _catalogBLL is an instance member.
However, since you create a new instance of CatalogBLL on every request, why not do so once more?
[WebMethod]
public static UpdateSomething(int i)
{
CatalogBLL catalogBLL = new CatalogBLL();
catalogBLL.UpdateSomething();
}
You can't call because pagemethods are static...
A static method is simply one that is disassociated from any instance of its containing class. The more common alternative is an instance method, which is a method whose result is dependent on the state of a particular instance of the class it belongs to.
Look at John saunder's answer..