ASP.MVC Permissioning : Is there a way to control partial content ? - asp.net-mvc

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.

Related

Am I thinking about MVC correctly?

I'm writing an application that details an applicant's status in our company through Salesforce; when one of our employees enters their Enquiry ID, it shows their status (cleared, not cleared) and, if not cleared, what the applicant needs to fix before they can proceed in their program.
I want to make sure that I am thinking about my application's different areas correctly. Here is what I have:
Model: The applicant class has a dynamic function, such as Application.find_by_Enquiry_Token__c_and_Account_dot_LastName_from_Opportunity, and when requested it returns the information from Salesforce
Controller: Parses the returned data from Salesforce and creates hashes with the information, such as #applicant[:general_information] = {:first_name = data[:Account].first[:FirstName], :last_name = data[:Account].first[:LastName]}.
View: Displays the information generated by the controller. However, it has it's own logic and checks, such as changing the color of a div depending on if they are clear (class="success"), if they are not clear (class="danger") or if they have some conditional information (class="warning").
I think I have this correct, except I'm a little worried about my view because I have a bit of Ruby code in there to perform checks based on the returned data, mainly to colorize but also to show certain errors. Is this okay/does this follow standards? Or should I try to refactor my application and push this up to the controller?
I would say having some ruby code like you do in the view is fine as long as you aren't performing long queries or setting instance variables in the view. Also another sign to start moving code from the view to the controller is if you feel the view is getting cluttered and hard to understand. From what you said, this seems like it is not a problem though.
One thing I would recommend changing is to make the method name on the model shorter. Shorter method names are much easier to understand and as you have it, the method name is very long and unwieldy. Other than that, I think you are doing everything well!
Displaying the correct classes in the view is fine and can't really be done anywhere else. If you feel like your views are getting messy, consider dividing them into partials or using Haml for views instead of ERB.
Model is where your application's business logic goes, including parsing data, and everything related to your domain.
Controllers handle interactions with the user. So, basically, in a webapp if a user goes to a URL what should your application do. This should not be doing anything other than handing off tasks to other classes and then rendering a view.
Views are just that. They should be super simple and straightforward as possible. You can extract logic from views into helpers or even presenters/decorators. Views handle what gets displayed to a user.
In your app I would have:
SalesforceApiGateway class which handles communications with Salesforce, I wouldn't be surprised if there was already a gem out there to handle this.
A model class for each Salesforce resource you are accessing. These would setup the proper call to the API gateway to pull the right data for the given resource.
This could get hairy quickly and may need to be extracted further: 1 class for interfacing with the gateway and a model class the resources as you would want to access them from your application.
Your controller should not be parsing any Salesforce data, but rather taking a user request and and wiring that up to the proper model.
The biggest thing to keep in mind is your classes should be doing one thing and one thing only. If you can't talk about your class without saying "and" then it is probably doing too much.
So you have a class that interfaces with the API. You have a class that parses the API. You have a class that brings an api's resource into your domain, etc.

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

Display/hide menu items depending on logged on user

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.

prepopulate MVC Models with IOC - an alternative to caching?

I'm considering strategies for a simple-minded CMS implementation for an ASP.NET MVC site. The simple-minded part is that I've abstracted the values used in various partial views, all of which are user controls that share identical CSS layouts. So I'm populating the custom values in the identical partial views from the database where I can modify them occasionally using CRUDs.
The not so simple part is a reasonably efficient and logical abstraction of a standard UI element as a sql table row. But putting that aside...
I know I'm going to use some super-models to hand to each page the pre-configged models for the partial views. But if they are pre-configged and pre-loaded, where to put them until called?
The part that makes me think I'm a little insane to go this way is the load time for what is essentially static data. But then again, SharePoint!
So (I think) why not load it all in application_start? Why not? I answer! Then I get to use IoC for something that google returns not one link to good information from even one smart person who has ever considered that it might be a sane idea.
So does anyone have a better idea for populating a Model from the database using an IoC container other than putting a repository call in the constructor?
And then, does anyone think that putting these static-data models in an IoC container accessible to the controllers is a dumb idea?
Thanks,
S. Machino
Following several SOLID principles, keep your stuff as single-minded as possible. For semi-static data, first create a Repository that loads this data. This will load the data for every request. It works, but probably doesn't perform so well, but now you have the implementation you need.
The next thing you can do is to Decorate the first Repository with a caching Repository. This CachingRepository will read from the decorated Repository only once, and then keep data in memory.
Thus you respect Separation of Concerns.
If you scope the CachingRepository instance to be a Singleton, it will live until the application is recycled, effectively keeping the cached data in memory.
You may want to consider using the OutputCache attribute in your design. You can decorate your action methods that will return static data with this attribute and the framework will take care of caching.
Of course, you still need to handle when to invalidate the cache.

Code behind in ASP.NET MVC

What is the purpose of the code behind view file in ASP.NET MVC besides setting of the generic parameter of ViewPage ?
Here's my list of reasons why code-behind can be useful taken from my own post. I'm sure there are many more.
Databinding legacy ASP.NET controls - if an alternative is not available or a temporary solution is needed.
View logic that requires recursion to create some kind of nested or hierarchical HTML.
View logic that uses temporary variables. I refuse to define local variables in my tag soup! I'd want them as properties on the view class at the very least.
Logic that is specific only to one view or model and does not belong to an HtmlHelper. As a side note I don't think an HtmlHelper should know about any 'Model' classes. Its fine if it knows about the classes defined inside a model (such as IEnumerable, but I dont think for instance you should ever have an HtmlHelper that takes a ProductModel.
HtmlHelper methods end up becoming visible from ALL your views when you type Html+dot and i really want to minimize this list as much as possible.
What if I want to write code that uses HtmlGenericControl and other classes in that namespace to generate my HTML in an object oriented way (or I have existing code that does that that I want to port).
What if I'm planning on using a different view engine in future. I might want to keep some of the logic aside from the tag soup to make it easier to reuse later.
What if I want to be able to rename my Model classes and have it automatically refactor my view without having to go to the view.aspx and change the class name.
What if I'm coordinating with an HTML designer who I don't trust to not mess up the 'tag soup' and want to write anythin beyond very basic looping in the .aspx.cs file.
If you want to sort the data based upon the view's default sort option. I really dont think the controller should be sorting data for you if you have multiple sorting options accessible only from the view.
You actually want to debug the view logic in code that actuallky looks like .cs and not HTML.
You want to write code that may be factored out later and reused elsewhere - you're just not sure yet.
You want to prototype what may become a new HtmlHelper but you haven't yet decided whether its generic enough or not to warrant creating an HtmlHelper. (basically same as previous point)
You want to create a helper method to render a partial view, but need to create a model for it by plucking data out of the main page's view and creating a model for the partial control which is based on the current loop iteration.
You believe that programming complex logic IN A SINGLE FUNCTION is an out of date and unmaintainable practice.
You did it before RC1 and didn't run into any problems !!
Yes! Some views should not need codebehind at all.
Yes! It sucks to get a stupid .designer file created in addition to .cs file.
Yes! Its kind of annoying to get those little + signs next to each view.
BUT - It's really not that hard to NOT put data access logic in the code-behind.
They are most certainly NOT evil.
Ultimately, the question you ask yourself is this:
Does this code A) Process, store, retrieve, perform operations on or analyze the data, or B) Help to display the data?
If the answer is A, it belongs in your controller. If the answer is B, then it belongs in the view.
If B, it ultimately becomes a question of style. If you have some rather long conditional operations for trying to figure out if you display something to the user, then you might hide those conditional operations in the code behind in a Property. Otherwise, it seems like most people drop the code in-line to the front end using the <% %> and <%= %> tags.
Originally, I put all my display logic inside the <% %> tags. But recently I've taken to putting anything messy (such as a lengthy conditional) in my code behind to keep my XHML clean. The trick here is discipline - it's all too tempting to start writing business logic in the code behind, which is exactly what you should not be doing in MVC.
If you're trying to move from traditional ASP.NET to ASP.NET MVC, you might aviod the code behinds until you have a feel for the practices (though it still doesn't stop you from putting business logic inside the <% %>.
There isn't a purpose. Just don't use it except for setting the model
ViewPage<Model>
See this blogpost for more info.
At this Blogpost is a working example of removing the code behind.
The only problem I'm stuck with is that it is not able to set namespaces on the class.
The codebehind provides some of the strong typing as well as the intellisense support that you get in the view. If you don't care about any of these two features, you can remove it.
For example, I typically use the NVelocity ViewEngine because it's clean and pretty straight forward.
This is a great question. Doesn't MVC exist in the ASP.NET environment, without using the specific MVC pattern.
View = aspx
Controller = aspx.cs (codebehind)
Model = POCO (Plain Old C#/VB/.NET objects)
I'm wondering why the added functionality of MVC framework is helpful. I worked significantly with Java nd MVC and Java Struts several years ago (2001), and found the concepts in MVC to be a solution for the Internet Application organization and development problems at that time, but then found that the codebehind simplified the controller concept and was quicker to develop and communicate to others. I am sure others disagree with me, and I am open to other ideas. The biggest value I see to MVC is the front controller pattern for Internet development, single entry source for Internet Application. But, on the other hand, that pattern is fairly simple to implement with current ASP.NET technologies. I have heard others say that Unit Testing is the reasoning. I can understand that also, we used JUnit with our MVC framework in 2001; but I have not been convinced that it simplifies testing to use te MVC framework.
Thanks for reading!

Resources