How to declare a global variable or a public sub in a web application that all aspx pages can have access to?
use a static variable in one of your code files.
"Global" variables can be kept in Cache using Cache.Add, or Application state using Application.Add.
"Globally-available" methods are generally an antipattern and should be avoided. If you need a utility function you can add a static method to a class, but beware the Ball of Mud antipattern.
1.You can use session variables which will be available to all pages in the scope of current session.
C#
Session("name")=value;
2.You can use application variables which will be available to entire application code untill application ends.
Application("name") = value;
Global.asax inherits from YourWebSiteApplicationClass...
public class YourWebSiteApplicationClass : HttpApplication
{
public string GlobalVariable;
public YourWebSiteApplicationClass()
{
GlobalVariable = "GLOBAL_VARIABLE";
}
}
...and in any .aspx or .cs(.vb) file...
<% = ((YourWebSiteApplicationClass)this.ApplicationInstance).GlobalVariable %>
Return "GLOBAL_VARIABLE".
Create a PageBase class and have your pages inherit from it.
Related
I'm adding a custom control dynamically in master page code-behind:
try
{
// Add custom sidenav menu control dynamically
SideNavMenu sidenav = new SideNavMenu();
tempPath = Request.RawUrl.ToLower();
path = tempPath.Contains(#"/sitename") ? tempPath.Substring(7) : tempPath;
sidenav.MenuPath = path;
menuPlaceHolder.Controls.Add(sidenav);
}
catch
{
// Handle this - custom error form and email
// Master page needs access to base page LogError method
}
This is the base page with ErrorLog() method, which actually generates an email:
public partial class BasePage : System.Web.UI.Page
{
public void LogError(Exception error)
{
...
smtpClient.Send(message);
}
}
How can I call ErrorLog from master page code-behind? Or is there a better place to put the "common" ErrorLog method? Can someone suggest correct syntax or a better approach?
Place the LogError function in a class in your App_Code folder and probably make it a static function. If it's reusable through multiple projects, then place it in a seperate class library. Your BasePage class has no business implementing the details of logging errors and sending emails. Remember Separation of Concerns (SoC).
In fact, a library already exists to do this for you, called Elmah.
I highly recommend NLog for your purposes. It allows for configurable logging, including via SMTP. Your code would look like:
using Nlog;
public partial class BasePage : System.Web.UI.Page
{
private static Logger bpLogger = LogManager.GetCurrentClassLogger();
public void LogError(Exception error)
{
bpLogger.LogException(
LogLevel.Error,
"ruh roh",
error
);
...
//smtpClient.Send(message);
}
}
Because NLog is pretty efficient, you can instantiate a private static Logger object per page you are logging on. Additionally, the logger will automatically record which class it came from, and various configuration options allow you to change where it logs, how it logs and when it logs without changing any other code.
Here is a link to the configuration for sending errors via SMTP, for example:
https://github.com/nlog/NLog/wiki/Mail-target
It's a mature project that has been around for a very long time and can grow with your project as your logging needs grow.
The team and I are looking at Orchard to use as our CMS. We have a fairly large ASP.NET 4.0 WebForms app and we can only migrate the bits one piece at a time. With that in mind, we will still serve our aspx pages and slowly convert them into the CMS as time allows.
I've noticed on the docs # orchardproject.net/docs, link here, about how one does authorization inside a module. So all that has to be done is include IOrchardService in the constructor of a controller and it'll get injected at runtime.
public AdminController(IMyService myService, IOrchardServices orchardServices) {
_myService = myService;
Services = orchardServices;
}
Because the conversion process will be slow, ¿can I provide a constructor with the IOrchardServices on a System.Web.UI.Page subclass?
// something like this
public partial class Test : System.Web.UI.Page
{
IOrchardServices _service;
public Test(IOrchardServices orchardServices)
{
_service = orchardServices;
}
}
This does not work, throws an exception expecting a default constructor. If I place the default constructor, the page loads correctly but IOrchardServices is not injected. ¿Is this even possible?
I am using VS2008 and have a solution file which contains 1 Website and 1 Class Library Project.
The Class Library is a Custom Control which derives from Label. The Website contains a reference to the control - it builds successfully and the compiled .dll gets added to the Website's /bin folder. I can then use it in any of the website's .aspx pages without error.
What I cannot do, however, is reference any of the Website's data access methods that are in static classes in /App_Code from within the custom control.
I don't want to repeat the website data access logic all over again within the custom control when I know it will already exist in the website - I just want to be able to call a method from a class in /App_Code . If I try and reference anything in /App_Code from within the Class Library, it fails to build and says it can't find the Namespace or that it doesn't exist in the current context.
How can I achieve this so that the Custom Control builds as a standalone control, but can make use of classes in the website it gets used in? Delegates, possibly? Was hoping it might be more straightforward than that.
EDIT: I should add that the reason the control is in a separate Class Library is so that I can include JavaScript as an embedded resource within the Control. So when it's used in a .aspx page, it adds a WebResource.axd? style link to the page instead of a load of plaintext JavaScript in the <head> section.
EDIT 2:
In the website App_Code folder, I have a static class that handles data access (snippet):
[DataObject]
public static class DBAccess
{
[DataObjectMethod(DataObjectMethodType.Select)]
public static DataTable GetSomeData(Int32 SomeParam, DateTime OtherParam)
{
SqlConnection cn = SqlLibrary.GetConnection(DBConnectionString);
DataTable _dt;
SqlLibrary.SProcFill(out _dt, cn, "usp_SomeData_Select", SomeParam, OtherParam);
return _dt;
}
}
In the Class Library's custom control (which I want to build independently of the website's existence, yet be capable of calling its methods when used as a control in an .aspx page):
namespace MyCustomControls
{
public class StatusControl : Label
{
private Int32 _someProperty = -1;
private DateTime _otherProperty = DateTime.Now;
public StatusControl()
{
//some constructor logic
}
public void FetchData()
{
//what I'd **like** to do here is:
DBAccess.GetSomeData(_someProperty, _otherProperty);
//...but DBAccess isn't "visible" to this control at build time
}
}
}
I have:
MyNameSpace.MyClass1
MyNameSpace.MyClass2
i need to get value from MyClass1.myvar1 from MyClass2.
Should I do that with static variable
What happens with variable value if it is static in a web application.
Im using MyClass1 as: var mClass=new MyNameSpace.MyClass1(), and from that im using mClass.
thank you
No, you should not use a static variable here. Remember, static means the variable is global for the application. In ASP.Net, you have a single application instance that is shared among everyone who visits your site. Using static variables can result in one user seeing another user's data.
If the value context is global, than it is ok to use static variable. Remember that if the value is updated, its updated for all users. If the data is different or belong to a user, than never use static, instead instantiate object of MyClass1 inside MyClass2 method .
you can use following approach.
Declare MyClass1.myvar1 as public and access from MyClass2.
class MyClass1{
public int myvar1 = 7;
}
class MyClass2{
public void TestMethod(){
MyClass1 obj = new MyClass1();
int val = obj.myvar1;
}
}
In this case, your data is safe.
It is not OK to use a static variable within ASP.NET unless you take thread safety into account. A single request will generally run on a single thread. Different requests will probably run on different threads. (See http://blogs.msdn.com/b/tmarq/archive/2010/04/14/performing-asynchronous-work-or-tasks-in-asp-net-applications.aspx for some good threading information.)
Unless you study up on writing thread safe code, I would consider using the following objects instead to maintain static data:
Application - for application-wide static data
Session - if it's user specific static data
HttpContext.Items - if it's data to be used by different objects within a single request
HttpRuntime.Cache / HttpContext.Cache - to cache shared data that can have expirations / dependencies
All youneed is to make a new instance of your class2 and call your variable from created instance in class1 like
myclass1
{
string Variable = string.empty;
protected void YourMethod()
{
myclass2 c2 = new myclass2()
this.Variable = c2.Variable;
}
}
how can i access a public function in an .ascx file using C#?
Thanks
If the function is not static you will need to first obtain an instance of the class containing the function and then invoke the function on this instance. For example:
<%
// obtain an instance of the type containing the function
Foo instance = new Foo();
// invoke the function on this instance
string result = instance.Bar();
%>
Obviously it would be better to do this in the code behind file instead of polluting your markup.
Like other public functions in .NET Framework - via object reference. But sometimes Visual Studio doesn't automatically see your User Control's public members. Try to rebuild your user control and the site if IntelliSense window doesn't show it to you.
Where are you calling the function from? The containing page? Masterpage? Parent control? The control itself? Regardless, you'll need to somehow obtain a reference to the control instance (unless the method is static) in order to invoke this method. And the type of your reference must match that of the class that defines the method.
Edit:
MyControl myControl = (MyControl)Page.FindControl("Id_Of_The_Control");
if (myControl != null)
{
myControl.TheMethod();
}
if you don't want to add your ascx control into a placeholder programmatically, just implement IAttributeAccessor and IUserControlDesignerAccessor interfaces to your user control class like;
public partial class yourascxclassname: System.Web.UI.UserControl, IAttributeAccessor, IUserControlDesignerAccessor
you can access only public members of your ascx control.