Public static readonly objects c# - c#

Is there any disadvantage to using public static read-only objects in a web application? I have not used them before.
I have a web application that needs to change the display on the page depending on the user's permissions and the state of their existing action.
This is the static class which returns the custom object for their abilities.
public static class Abilities
{
public static readonly Ability ViewPage = new Ability()
{
LinkText = "something",
Hidden = false,
//Any other additional unchanging properties
}
}
Then for each user when they log in there is a method that sets the abilities that they should have
public class User
{
public List<Ability> GetMyAbilities()
{
var myAbilities = new List<Ability>();
if //some programming logic here
myAbilities.Add(Abilities.ViewPage);
return myAbilities;
}
}
This seems to be working as expected, but I wonder if there were any disadvantages or problems when using this method for multiple users?
As per comments - to add a bit of detail. The user class is created for each user when they log in to the web application. The list of abilities refers to stuff that they can do when they have logged in. Each user will therefore get a list of the abilities that they have when they log in to the Default page.

Related

How to combine database access and cache in asp.net mvc (An object reference is required for the non-static field, method, or property 'Module.dbApp')

This is actually 2 questions in one.
I have an asp.net mvc application where I have to load a list of Modules, its just a simple list with ID, modulename and a class name to render it on the view with font awesome.
My model is like this:
public class Module
{
[Key]
public int Id { get; set; }
public string ModuleName { get; set; }
public string FontAwesomeClass { get; set; }
}
Because the module list is a Partial View that will render some icons on the top navigation bar, I dont want that for each refresh of the app, it goes to the DB, so it must be cached(I am using Azure REDIS Cache, not relevant for the question anyway), so instead of calling the DB context directly from the controller, I am calling a Cache Class that will check if the cache object exists, if not it will retrieve it from DB, if it does, it will return it from cache.
This my solution structure:
http://screencast.com/t/uayPYiHaPCav
Here is my controller Module.cs
public ActionResult GetModules()
{
return View(Cache.Module.GetModules());
}
As you can see the Controller does not have any logic where to get the data from.
Here is the Module.cs (on the Cache Namespace)
public class Module
{
private AppDataContext dbApp = new AppDataContext();
//Load modules from cache or from database
public static List<Models.Module> GetModules()
{
IDatabase cache = Helper.Connection.GetDatabase();
List<Models.Module> listOfModules = (List<Models.Module>)cache.Get("Modules");
if (listOfModules == null)
{
return dbApp.ModuleList.ToList();
}
else
{
return listOfModules;
}
}
}
Here I have a compiler error which I am not sure how to best fix it:
Error CS0120 An object reference is required for the non-static field,
method, or property 'Module.dbApp'
So that was my first question.
The 2nd question is more about the design pattern, do you consider this correct or not? the way I am trying to get the data from Cache, and its actually the Cache class which checks if data is on it or if it has to go to the DB.
First Question: make your private member static
private static AppDataContext dbApp = new AppDataContext();
2nd Question: your cache strategy seems pretty standard. The only thing is that you might want to expire cache data. For example, the cached data can get old and the longer it stays in the cache the older it gets. You might at some point want to expire it and get fresh data again.
Update:
#EstebanV for code sample (this off the top of my head, don't assume that it compiles):
/**
ICachedPersonDao abstracts away the caching mechanism
away from the core of your application
**/
public CachedPersonDao : ICachedPersonDao
{
private IPersonDao personDao = null;
public CachedPersonDao(IPersonDao personDao)
{
this.personDao = personDao;
}
public Person GetPersonById(int id){
bool isInCache = CACHE.SomeFunctionThatChecksInYourCache(id);
if (isInCache)
{
return CACHE.SomeFunctionThatReturnsTheCachedPerson(id);
}
else
{
//Well it's not in the cache so let's get it from the DB.
return this.personDao.GetPersonById(id);
}
}
}
/**
IPersonDao abstracts database communication
away from the core of your application
**/
public class PersonDao : IPersonDao
{
public Person GetPersonById(int id)
{
/** Get the person by id from the DB
through EntityFramework or whatever
**/
}
}
Usage:
In your controller, use ICachedPersonDao if you want to attempt to get from cache or use IPersonDao if you want to get it directly from the database without checking the cache.
Like I said, you should learn Dependency Injection it will help "inject" these dependencies into the classes that uses them.
I say again, this is off the top of my head. It won't compile. It's just to illustrate the concept.

replacement for static variable

I am developing an ASP.NET MVC 4 application. userMenus is a static variable that is loaded every time a user logs in.
public class MenuCL
{
public static List<UserMenu> userMenus = new List<UserMenu>(); // the static variable
}
public class UserMenu
{
public decimal MenuID { get; set; }
public string MenuName { get; set; }
public string Controller { get; set; }
public bool Permission { get; set; }
}
I use that static variable to check whether or not the logged in user has permission to a menu/controller in a custom authorize filter.
It works fine when a single user is logged in, but when two or more users are logged-in, it's all messed up, I mean the error page("you don't have access to this page") is displayed to a user that has permission to the menu/controller.
Only now I realized it's the static variable that is causing all the trouble, after I read this :
The static variables will be shared between requests. Moreover they will be initialized when application starts, so if the AppDomain, thus application gets restarted, their values will be reinitialized.
So I need a replacement for this static variable. Anyone has any suggestion?
You can still use a static field which is a property that provides access to a session variable.
public static List<UserMenu> UserMenus
{
set
{
Session["UserMenus"] = value;
}
get
{
return Session["UserMenus"] == null ? new List<UserMenu>() : (List<UserMenu>) Session["UserMenus"];
}
}
In order to get this working on a web farm which uses a session state server (or sql server), you need to put [Serializable] attribute on top of UserMenu.
I don't think, this way you need to modify your code very much.
My question is, why do you want to use static variable? Do you want to share the values across the application? In this case you can better use session.
Updated
Assume lst as a non static List of UserMenu. Then you can use the following method to store it in session and get it bak whenever you want.
To store
Session["usemenulist"] = lst;
To get it back
try
{
lst = (List<UserMenu>)Session["usemenulist"];
}
catch
{
}
Note
If you are getting the values from the database lo load it to the List for the first time, then you can query database to get it from the database whenever you want, instead of storing it in the session. (This is another option apart from Session, you may try this way also if you want.)

Best practice to store temporary information

When my user in the students Role login to the system, he can select various classes that he's enrolled. I already have a filter that'll redirect him to the select class page so he must select a class to access the system, and change it anytime he wants and the whole system's context will change.
As for now, i'm storing IdClass in the session variable, using the code below, and the system uses it to filter all the related queries and functions, like showing all the lessons from the current class. My question is: is this a good practice? Is this right or is there any better and efficient way? I'm trying to follow patterns.
[Serializable]
public sealed class Session
{
private const string SESSION_FOO = "STUDYPLATFORM_GUID";
private Session()
{
this.IdClass= 0; // Construct it to 0 so it evaluate as there's no Class selected.
}
/* This is the session's public IdClass that
i can get and set throughout the application. */
public int IdClass { get; set; }
public static Session Current
{
get
{
if (HttpContext.Current.Session[SESSION_FOO] == null)
{
HttpContext.Current.Session[SESSION_FOO] = new Session();
}
return HttpContext.Current.Session[SESSION_FOO] as Session;
}
}
}

dealing with static list

I have create a permission object that stores userId, Groups user is in and userĀ“s permissions. This is a public class
I also need to have a static object that stores a list of those permissions objects that if a administration changes anything in the permissions all changes apply immediately for every logged user
I have a couple of questions:
Should I create this static object when the first user logs in or there is a mechanism a should use to create that list before the first user log-in (For instance when we start our app on IIS)?
Would it be easy to remove the item list for a specific user when it log-out?
This is a system requirement that permissions settings take effect as soon as the administrator make changes.
Edit 1:
public class permissionTemp
{
public static Guid userGuid { get; set; }
public static string[] grupos { get; set; }
public static string[] permissoes { get; set; }
}
public static class security
{
public List<permissionTemp> userPermissionSet { get; set; }
}
Think about a singleton, so you do not worry about creation time:
Singleton:
public class Permission
{
private Permission()
{ }
private static Permission _instance = null;
public static Permission Instance
{
get
{
if(_instance == null)
{
_instance = new Permission();
}
return _instance
}
}
Now you can have access to the same instance with
Permission.Instance
The object is created at the first access. So in the private constructor you can add your code to read the permissions fom database.
You can use the Application_Start method in the global.asax to run some code when the website starts for the first time. This will run before the first request is processed.
You can use the Session_End method in the global.asax to remove the item from the list. Also you can do it at the same time where you execute FormsAuthentication.SignOut (if you use Forms Authentication).
Note: I would use some locking mechanism to prevent multiple simultaneous access to the list. An alternative place to store the list would be in the WebCache. This is used by all users, so if it is updated by person x, next read from person y will be the updated version.
First of all i recommend to avoid creating static object for storing such sensetive information and also if any user has closed browser without clicking "Log out" then object will not be removed for that particular User.
Still if you need to do this to meet your requirement you can create it in that object in Applciation Start Event on Global.asax file when application start first time.

Creating a Global Object?

I'm trying to achieve the following:
When a user has been successfully authenticated, I need to create a Global user object which I can access from different Forms (or classes).
I was looking through the Data Sources available in VS, and saw there's a "Object" option which may be suitable for what I'm trying to achieve. The trouble is, I have no idea how it works.
Can anyone point me in the right direction?
Thanks.
Assuming that this is a Windows Forms application, you can create a User class that is stored in a static ApplicationState class.
Steps:
1) Create your user class to hold information about the user:
public class User
{
public string Login { get; set; }
//.. other properties
}
2) Create your ApplicationState class:
public static class ApplicationState
{
public static User CurrentUser { get; set; }
}
3) In your login process, create a new version of the user class and assign it to the ApplicationState.CurrentUser property:
public void CompleteLogin(string sLogin)
{
User user = new User();
user.Login = sLogin;
ApplicationState.CurrentUser = user;
}
4) You can now use ApplicationState.CurrentUser just about anywhere in your project.
It's called a Singleton, and it's a Bad Thing (especially when its state can be mutated). Investigate Dependency Injection (DI) instead. There's even a .NET-specific book on it.
Per request, here's a simple (probably oversimplified) example of doing DI manually. A DI Container library (also known as an Inversion of Control or IoC Container library) can simplify the process of "wiring everything up" in the composition root, and usually also provides lifetime management and other features.
// Composition root of your application
void Main()
{
// Only instance of user we will ever create
var user = new User();
var instance = new MyClass(user);
}
public interface IUser
{
string Name { get; set; }
}
public class User: IUser
{
public string Name { get; set; }
}
public class MyClass
{
public MyClass(IUser user)
{
if (user == null)
{
throw new ArgumentNullException("user");
}
_user = user;
}
private readonly IUser _user;
}
You could use or create a public List making sure that you only add the authenticated users to the List once they have been validated you could even do this via encapsulating field access, create a List or string[] property what you are asking you probably would want to create a class level Property.

Categories

Resources