Best way of sharing user specific variables around my MVC4 app - c#

I am building an MVC4 app using razor, I have done many in the past but I want to roll some best practice in to this one in terms of dealing with variables.
The situation is that I have a logged in user (logged in meaning a windows authentication, with that user name matched to a user in my user table). That user comes with a set of profile options such as "canViewReports", "canEditPerson" etc etc.
Now, there are two prongs to those profile options. First is that my presentation layer needs to customise itself depending on what is presented to it. So profile 1 has canViewReport set to false so the tab for reports will be hidden. Profile 2 has it true so the tab will be shown.
The second prong is that if my savvy users type in /reports/index, I need to pick that up and block access for profile 1 but allow profile 2.
Ok, so at the moment I am using a base controller that is decorated with a [UserDataFilter], that user data filter calls a method that checks the current session for a set of keys and if they are missing assigns them. I put each of those profile options for the current user in to the session. I can then use the session variables in my presentation layer and also in code.
My concern is that that is messy looking in my code having to put this kind of thing everywhere:
(bool)session["canViewReports"] everywhere in my razor.
That lead me to try using the viewstart.cshtml and setting App variables in there that I can use in my razor a bit cleaner. In viewstart I set:
App.canViewReports = (bool)HttpContext.Current.Session["canViewReports"];
I can then just use App.canViewreports everyhwere in my views without too much trouble.
My questions are:
1) Is App.canViewReports for the entire application at an IIS level, or does each connection to IIS get its own pool of App. variables. The thing I want to avoid is the first user setting the variable and every other user that subsequently uses the application getting that value! (on different computers)
2) Is there a better way of doing this!!!
Many thanks
Iain

I would use User.IsInRole("canViewReports") in my razor logic to hide and show the menus item. If you build you menu in you layout you only need to do this once.
I would then further protect the action method by decorating the method with
[AuthorizeUser("canViewReports")]

You could create an ISessionService that stores the session information you need.In this way,you can implement it however you want and have full control over it.It could be retrieved easily via a DI container and it's easy to mock.

Related

Best practice for persisting User State in special kind of Asp.Net Mvc application

I will try to explain my situation and what I wanted to do. There is not any difficult and rare situation, but I can't find any relative questions or articles in internet.
I have created a web application on ASP.NET MVC 5. Users are not going to enter my application directly. Users will enter let's say to CentralInformationSystem.com. Then they must login to this website one of supported ways. After signing in, they will see a list of applications. There will be applications which has been allowed to use for the signed user. One of this applications will be my application which has developed in Asp.Net MVC.
And the main point is that our applications will not be opened in other tabs or in current tab and so on. Our application will be opened in a big iframe inside the current tab.
And other main point is our applications and CentralInformationSystem.com belong to other domains.
The other question of course is, how then I can now which user has signed in? And the answer is, CentralInformationSystem.com sends encrypted data with the query string to our web site. For example, the URL will look like that:
MyMvcApplication/Home/Index?Token=jkndid758adsai==qwdbqwiudhqwadoqidwqq=wqdiqw
Also keep in mind that they will always sent different tokens.
And after that, I will decrypt token and find to which user it belongs. Also keep in mind that, one Token can be used only once.
1. What type of application is my application?
User will enter very big form. It can actually take almost 3-4 hours. So, I have tried some-type of wizard logic. After entering some portion of datas, I will insert them to the database, get identifier from the database and store it somewhere and take the user to the next level and so on.
2. What I want to achieve?
I want to create such logic that, some identifier variables values must be stored in such place that never must be expired till the user closes browser or signing out. I don't want to increase session timeout to 5-6 hours.
3. What if user opens my application in more than one tab?
Alongside 2 I have also one problem, that user can open my website inside iframe more than one tab. I know that, in Asp.net we can differ session per each tab. But, I don't want to store datas in session, because user can stop filling forms after 20 minutes or 4 hours. Also, I cannot use cookie, because cookies will be same for all tabs.
My other option is, to inject hidden inputs with encrypted value to all views. But, I can't find how to automatically add these datas to each views. Also, it doesn't seem to me as most efficient way.
The other logic is to prevent user to open same application in more than one tab with differen tokens. But, don't how to achieve this also.
Additional:
I have read almost all articles and questions/answers. I know how to make it work. But, I want the best approach. Neither of my approaches are efficient.
Use your own concept of a persistent session that is identified by a hidden input on the page and does not expire, or at least does not expire for a very long time. Have all of your controllers derive from a single base controller and use the OnActionExecuted to add the session "key" to the ViewBag when the result is a ViewResult (you won't need it for partial views or JSON, etc). Every page can then access the ViewBag and create the hidden input - probably you want to use a partial view for this and simply include the partial on every page. Store the data associated with this session in the database.

MVC 5 User Online with Identity

I've started to work with new ASP.Net Identity and I would like to know how does identity handle IsOnline ...? Does it have this option?
And another question using mvc 5 and identity, how do i best keep track of online ppl? Should i still use the old method when user closes the page and then js unload to set the the property in db to IsOnline to false?
But what if user has 2 instances or even 3 instances open of the website and navigates throught different pages, how can i still correctly and synced maintain the online / offline?
Maybe there is some sort of library for that or some new way of doing that? Maybe some helpful link ....
Thanks
By default identity doesn't have anything similar to IsOnline, so you would have to add this functionality yourself. You can probably do it with a combination of adding a lastActivity property for the user, along with extending UserManager and overriding all the methods you wish to consider the user being online to update this field. Alternatively you could just manually update the lastActivity where appropriate in your app, which might be easier.

Different asp:menu on a user basis

I have a oracle database which stores menu and user data, for a local Intranet.
The data includes which usesr have access to which pages.
Originally I created a class which extened the StaticSiteMapProvider class, however when this went in to the testing environment, i found that this was cached for the whole site (and not on a user basis). After reading up on line on various forums, it was suggested that I should inherit from SiteMapProvider as this would enable me to have a seperated instance of thet SiteMapProvider and ASP:MENU item on a user basis, however this still hasn't solved the problem.
Currently I have a user control, which conrains the asp:menu, and uses my custom site map provider as its data source.
Could anyone suggest how I can display the menu on a user basis, driven from database authorisation?
Also the whole menu should still appear to all users, it only after thy click on a menu node that they will find out whether they have access to that page/node.
Thanks
You can make use of Roles on the SiteMap to define what menu will appear.
There are two things here. If you have static collection of nodes and then you want to show/hide them based on user accessibility then you should override IsAccessibleToUser
method to tell if the given node if applicable for the current user (accessible from given HttpContext).
In case, your nodes collection/hierarchy changes per user basis then try overriding BuildSiteMap to load different nodes for current user. However, I am a bit doubtful if StaticSiteMapProvider is the correct base class in this case. Probably you need to override from SiteMapProvider.

How can I stop applications from using Sessions when a request is made by a bot?

The solution is for a project in which changing all instances of Session[string] is not an option. My thoughts have been implementing the SessionStateStoreProviderBase. I understand that creating a class Session and having properties like Session.UserName would be a good idea.
Edit: The goal here is to turn off Sessions per user request, not application wide, without changing code in each aspx page.
First you need a way to tell a bot from a human apart.
When you're through, consider what do you want to achieve.
If you wish to disable Session to bots, then be sure it won't break you site. If a search engine bot gets a crashed page, it will index and rank it as such.
Set up your robots.txt file to direct (most) bots to a page of your choice, where you have control over session and other information. If you want free access to all pages, you have to put in code to distinguish bots by http header information - that's a research project in itself.

Rolling My Own ASP.NET Registration Wizard

I imagine this is a pretty hard question to answer without sitting down and looking at all the source code, but I figured I'd post it anyway and see if you all had any conceptual thoughts on a process we're using in my company.
The project I'm working on currently is a self-registration page for our end users. Previously, we used 3 separate ASP.NET wizard controls for each of our different registration processes. It was consistantly stated by our customers that the process was very confusing, and they never knew which of the three different processes they should be completing. So after being asked to compile the three apps into one, I quickly found that the registration wizard controls are not very extensible. The new process needed to be very dynamic, so the static, one path, wizards were not fulfilling the needs.
So in an attempt to make a more dynamic process, I rolled my own registration app that relies on session state to walk a user through registration. The way I have it set up currently is using binary flag values for possible steps in the registration. I then have a integer value in SessionState that I update after a user completes a step.
Example:
const int accountNumberStep = 1;
const int userPassStep = 2;
const int usernameReclaimStep = 4;
/* code snipped */
// Code at the end of step Username/Password selection
// at the end of Username/Password selection step, update session state to record that step was finished
SessionState("stepsCompleted") = (int)SessionState("stepsCompleted") | userPassStep;
/* code snipped */
// Code at the beginning of each step to verify previous step was completed
if (!((int)SessionState("stepsCompleted") & userPassStep == userPassStep))
{
RedirectToPreviousPage(previousStep:=userPassStep);
}
Another major piece of this (this is where the dynamic piece comes into play) is using a session variable to keep track of the type of registration they are going through. In other words, they might have three different types of registration they can go through:
Normal Registration
Account Update Registration
Obtain Disabled User Account Registration
The registration type the user is completing is determined as they progress through the registration. For example, after a user types in there account number, I determine that they are not a new user, so they will be either an update, or a re-enable. This path is stored in the registration type variable in session state.
The final major piece of the app tracks text box values, radio box selection, etc. This is all stored in the SessionState as well, so if at any point in the process, the user wishes to back up a step or two, they will not lose the previous values they entered. These values are also used in the final step of the registration process in which the customer is actually registered on the back end database.
As you can see, all of this is vary similar to what an ASP.NET wizard control does. With the exception of the registration type variable. This allows me to branch the registration into different paths at any given point in the process.
Anyway, sorry again if this is confusing. I'm mainly hoping someone will come by that has done something similar and might be able to give me some advice.
Thanks in advance for your help.
CJAM
The wizard control is based on the MultiView control, which basically provides a means of showing one (and only one) view at a time. The only difference is that you are required to control navigation manually with the MultiView, therefore allowing you non-linear progression through the steps.
With the MultiView, the values of all controls in all the views will be stored in the ViewState, so there is no need to store them in the Session. Buttons within each view can post back, and based on the values of other controls, you can show a specific view.
Check out the ASP.NET Quickstart on MultiView and View controls

Categories

Resources