Display/hide menu items depending on logged on user - asp.net-mvc

In my web app, I would like to show an "Admin" menu link only to users who have been added to the database as an administrator.
What would be the best way to do this in ASP.NET MVC 2?
At the moment, I am doing it by checking whether the user exists in the Admin database table for every page. Obviously, there must be a better way to do this.
If it helps, I am using Windows Auth.

You could probably save the admin state in a session variable or something, but it seems more appropriate to create a partial view with the menu (if you haven't already) and just have the check in there. You'll still have a database call for it on each page request, but no duplication of code. And unless you have performance issues right now, one extra call really isn't that big of a deal.
If you do have performance issues, make sure you optimize your own code, have all the correct indices on the db etc. A lot of performance gain (especially in db related problems) can usually be made by re-structuring how things are done, instead of what is done.
UPDATE:
In ASP.NET MVC 2 there is actually an even better way you could do this, combining Html.RenderAction() and AuthorizeAttribute (or possibly write your own inherited attribute that sets a flag instead of returning an error when the user is not authorized). That way you would minimize view logic, and conform better to the MVC principles.

Related

ASP MVC vs. WebForms: using SessionState for user logon

i've a question regarding handling of user logon while porting an application to MVC:
in the "old" WebForm days, developers simply used the SessionState object to set a user to logged-on, by -for example- simply putting the userobject into the SessionState (and this userobject holds simple properties like name/lastlogon/etc.)
this stuff worked very well for us, and i've seen lots of applications doing it that way
yes, i know there is this MembershipProvide-thingy, but i've never used it
Now, in MVC, everybody tells me that "using SessionStat for this is bad" and "apps built that way are flawed in design" and that "there are tons of security risks" and so on.
I've used this method because it worked for the app very reliable, it was simple to implement and it covered all stuff we need.
(Sure, there is the thing with recycling web worker process and emptying the session - but thats not a problem in our case, since the app runs for each country on a dedicated machine)
I've read tutorials, telling me to put that stuff in the DB and -attention- doing a request to the DB to check if the user is logged in, per EACH request? But: Under no circumstances, this is a doable way since i want to keep DB requests on a minimum.
So my question is:
A) whats wrong using this way also in the new MVC app?
B) whats the best way to handle this scenario in a newly built MVC app?
Regarding the session-in-DB-idea: instead of doing this, i'd rater setup an additional service, like a "session-manager" thats get query over the network, but such simple requests should not go to the DB - isn't that a good idea?
Any idea, hint /etc. is highly appreciated since this scenario is really confusing me :-X
A)
A fundamental principal of the asp.net mvc framework is that its stateless. Data is passed around using http requests and sent to the views in viewmodels. Web forms tried to maintain state with viewstate etc thats why you would have seen the logged in user in session approach. Thats not to say session shouldnt be used completely in asp.net mvc, there are some circumstances when it can be useful. Like maintaining a 3 step form process that has to be persisted on the last step. But generally we already have a recommended way to handle the user logins, and thats forms authentication
B)
For accessing the user object, you can create a custom identity implementing the IPrincipal interface and add the required user fields you need. Then set the custom identity in a global filter and access it in your action results. Regarding not wanting to query the database for every request, why dont you just call it for the initial request, then cache the result until the user is updated where you then can reload the object and set it in the custom identity again.

How do I design MVC apps with view auditing in mind?

We're going to be building an application using MVC 4. A key requirement is view-level auditing. In other words, we must be able to show who accessed a view/screen (person details, for example), the parameters to create the view and when the view was accessed. This is a new application so we can do almost whatever needs to be done to address this requirement.
The database will be SQL Server 2008. Data access will include EF 4.x, possibly 5.x but not a sure thing.
My question, how do I get started designing this feature? Are there any sample applications out there?
Don't mind auditing at view level. I think it is better to audit actions. You can do this using global action filters (for example here).
EF does not work very well with Views. You might be better of with either a straight ADO.NET persistence layer that you hand code, or Linq2Sql is a little better about using views (you still have to hook them up manually though). nHibernate would probably be the best ORM to use.
EDIT:
#user1469655 - You have a very fundamental misunderstanding of how MVC works. The "view" is not a page. It's a template. The "page" as you might consider it (ie accessing a specific url) is really a combination of two different things, a route and an action. An action can cause a specific template (view) to render, but there is not necessarily a 1:1 correlation between action and view.
An "action" is a method of a controller. This is mapped to a URL by a route. Typically (but not necessarily), this means something like this:
http://www.my.site/controller/action
When a user visits this URL, it causes the action method to be called, and potentially for a view to be rendered. Different actions can render the same view, because this is nothing more than an html template that can be rendered at will by any action method.
So what you want to do depends on what you are actually logging. It makes no sense whatsoever to log access to the view, because that doesn't actually mean anything. What you want to do is log access through the action, or possibly even log it through the route.
The simplest way to do this is to use a global action filter that is called before every action, in that filter you can log the information you need to (user id, date, time, action, referrer, whatever).. and it gets called for every action. It will not, however, get called for ignored routes (such as for content like javascript, images, css, files downloaded directly, etc..). If you need to log those, then you will need to control access to them via an action.
There's a good tutorial on Action Filters here
http://www.asp.net/mvc/tutorials/older-versions/controllers-and-routing/understanding-action-filters-cs

ASP.MVC Permissioning : Is there a way to control partial content ?

I am writing an ASP.MVC application and I know you can use authorisation filters on the cotrollers to control access to the pages but I am wondering what is the best approach to do if you want to control access to protected data within partial views.
From what I have read ASP.MVC doesnt offer this level of granularity.
This seems easily enough by adding the user permissions to the model as an attribute and then using a simple factory to decide if the view should be rendered or a blank view be returned.
So far I have
RenderPartial(PartialFactory.IsAllowedToRender("partialName", Model.Security), Model)
and the Factory either returns the view requested or a blank partial view.
Has anyone tried this before or knows why no one does this (apart from the extra effort)
We have done similarly with extension methods for HtmlHelper.
RenderPartialIfExists and so on. No shame in doing this if its something you are going to need frequently.
Doing it without the extensions as you have works as well, but its not as clean to read. Also, consider adding your security information to HttpContext.Current.Items, that way you don't have to pass it into the models all the time, and anything that needs to take advantage of it, helpers, controllers, etc have easy access to it, and you only have to fetch it at the beginning of a request.

asp.net mvc - membership provider

For my ASP.NET MVC app, I just find dealing with unique-identifiers harder, so I have added my own field to ASPNET_USERS table - UserIdInt (which is actually a bigint!) So most of user operations use userIdInt as reference.
Anyway, I am debating between two approaches:
1)When a user logs in, look up from the database and store the userIdInt in a session variable and any-time session variable slips away, re-look it up and put it back in session variable. (It's okay to use sessions in MVC app, right?)
2)Any time an operation needs to be performed, simply pass userName to database and take care of UserIdInt at database side by doing joins and such on ASPNET_Users table any time an operation from user needs to be performed.
I am heavily leaning towards 1)... but I want to make sure I am on right track.
I asked this question on Serverfault first, but I was told to ask this question here.
progtick,
you may be far better looking into the use of custom profile providers as this would allow you to leave the aspnet_* tables as is (which is a good idea in case a later version of sqlserver changes how they operate) plus offer the additional bebnefit of having a multitude of additonal profile related properties availabale to your application. i can't overstate enough the benefits in going down this track as i've found it very useful to have such an approach in both my standard asp.net apps as well as my mvc ones.
you can get a feel for what's involved in this by looking thro a couple of these links:
here's one on SO for starters:
Implementing Profile Provider in ASP.NET MVC
and one from my old mate, lee dumond:
http://leedumond.com/blog/asp-net-profiles-in-web-application-projects/
hope this helps
An alternative approach is to alter the forms authentication ticket to add your unique id to the data stored in the cookie. Then, by implementing a custom IPrincipal you can have your unique id available anywhere that the User object is available.

ASP.NET MVC: cache with non-cachable portions

I have a heavy page that is cached. This is okay for anonymous users. They all see the same page.
The problem is for logged in users. They should have minor parts of the page re-rendered on every request (like personal notes on content in the page, etc.)
But still all the rest of the page should be cached (it does tons of SQL and calcuations when rendered).
As a workaround I put placeholders in page templates (like #var1#, #var2#,..).
Then I make controller method to render View into string, where I do string.Replace #var1# and other into real values.
Any cleaner way to do such kind of partial "non-caching"?
This is called donut caching.
The ASP.Net MVC framework doesn't currently support it, but it's planned for version 3.
To start things off, it might make sense to go through the page and see if there is anything about it that you can do to streamline or reduce the weight. Depending upon how bad things are, investing some time here might pay off in the long run.
That said, in regards to trying to server the content to anonymous as well as logged in users, one option is to have two versions of the page: one for anonymous users and one for logged in users. This may not be the best approach though as it means that you now have two versions of the same page to maintain.
Given the lack of support doughnut caching mentioned by SLaks what I would likely do is try and cache the results of the calculations that are being done for the page (e.g. if you are querying a database for a table of data, cache a DataTable that you can check for before running the operation) and seeing what that does for the performance. It may not be the most elegant solution in the world, but it may solve the problems that you are having.

Resources