Code behind user control - asp.net-mvc

How would one go about performing controller actions from withing an ASP.net MVC user control?
My scenario is that I have a userID and I want to transform it into a name from the database. To do this I've annotated my model with a display type and put a User template in the shared display templates but I'm not sure where I should write the code which does the lookup to convert from userID to user name.

I think that code ought to go into your models and you should be calling it in your controller and passing it to your user-control in a viewdata. This is if I understood your question.

I would just have the model expose the name and not the userID. This way your view (user control) is only displaying the name and not trying to do a DB lookup. Your "User Control" model would be responsible for how it gets the name, i.e. the DB from your question.

In short, you don't do that.
You should be passing the necessary data to the MVC user control from the View, which in turn should be getting it's information from the controller.
The view (or user control) should not have any knowledge of the controller. You may want to use RenderAction instead of a user control if you feel that the view shouldn't be responsible for passing the necessary information into the user control.

Related

MVC passing values through several views

I have a login view for a user to authenticate: after he inserts his username and password, the next view has a section with welcome, username message. I pass this information through a ViewBag.welcomeMsg and everything is smooth.
When I advance to another view, that section no longer contains the message as the ViewBag.welcomeMsg is defined in the first login controller and gets erased after that.
I don't want write in every controller ViewBag.welcomeMsg = "...";
My question: is there a way to pass a variable like ViewBag that persists and can be accessed from every view of the web application? Like a static field?
If you just want to show the welcome message on your view when user is authenticated then just modify your view like this :
#if (Request.IsAuthenticated)
{
<text>Welcome, #User.Identity.Name</text>
}
Can check with the TempData which will be available till start of the next view rendering. so that you can set it to the other viewbag from tempData.
It very much depends on how you handle the authentication process. If you are using FormsAuthentication for example, then the user information will be stored in User.Identity.Name. You can access User property from various contexts like controller, view, etc.
On the other hand if you are handling the authentication by yourself, my suggestion to you would be to do any of the following (I am writing this from top of my mind, so if I miss a name of a property, forgive me):
Store username in a cookie, and in Global.asax handle PostAuthenticated event where you will read the username (if authenticated) from the cookie. After that create a GenericPrincipal object with GenericIdentiy and assign it to a Controller.User
Store the information in a session (the easiest of all) and pass it around. However, the problem with this is if you have a sessionless controller in which case you cannot rely on this approach.
I wrote an article a long time ago about working with roles and principals, but you can get a picture on how to handle your problem with this solution http://mvcdeveloper.wordpress.com/2013/06/08/passing-user-roles-to-httpcontext-user/

Mvc How safe is viewbag?

My website is built around tabs. I have one single page with multiple partial views that display each tab.
The problem im facing now is I want to loop through files that the user has uploaded and display them in one of my partial views. This requires me to send the file list as a paramater in my action like this:
//Uploadedfiles is a function that adds the files to a list.
var files = UploadedFiles();
return View(files);
Because im only using one view to display all my partial views, i get:
The model item passed into the dictionary is of type 'Microsoft.WindowsAzure.Storage.Core.Util.CommonUtility+d__0`1[Delamapp.CloudStorageServices.UploadEntity]', but this dictionary requires a model item of type 'Delamapp.Models.LoginFolder'.
This means im required to not send a model item to my index view. Now, the only thing i can think off is adding my file list to viewbag and then display them on my view. BUT.. The files require high security. How safe is viewbag? Can you for example store sensitive login information in there? Can you think off some other way to accomplish this?
Thank you in advance
You can pass a model item to your view, but the model item you are passing doesn't match the type of model that your view uses (that's what the error message says).
So you need to do one of the following:
Modify your view to accept the model type that you are passing to it
Put the data you want to pass into the model type that your view is expecting
Create a new model type for both your data and for the view, and use that
In terms of security, I don't think using a view bag versus model binding really enters into the question of security. Both are just ways of passing data in between the controller and the view, and that all takes place within the ASP.NET process (perhaps you have ViewBag confused with Web Forms' ViewState?).

how to access session in view asp.net mvc

I use MVC 3 with spark view engine. I have a data that should be accessed in every pages, the data base-on user login information. so I collect the data when user loged in and I put it on a session. I use a control to handle the data in site master ( master page ). and data in session will be binded to that control (eg. Dropdownlist ).
is it the best practise to handle data in master page on asp.net MVC ?
I try to create a base class for controller, buat I can't hold the login credential (HttpContext.User.Identity).
how can I access session data from View ?
I try to use #Session["mydata"] ( !{Session["mydata"] in spark view engine} but it didn't works :(
any helps ?
There are two general ways to handle this.
One is to use Html.RenderAction from your layout (master page). In that way you are packaging all of your data ahead of time into a model the master page will use.
The second way is to have your controllers inherit from another controller. When the base controller is instantiated, it is responsible for populating ViewData with the required data which is then displayed on the page. This requires all of your controllers to inherit from your base controller.
See listing 4/5 at:
http://www.asp.net/mvc/tutorials/passing-data-to-view-master-pages-cs
You could also do this via an action filter (and other ways too!!) but I think the above two ways are a bit cleaner
You should be able to get to the credential of the logged on user by calling System.Threading.Thread.CurrentPrincipal.Identity.Name in your controller base class.
That should allow you to populate the ViewData and then access the data from your view.
Alternatively if you still want to use the session, you should be able to access the session via - HttpContext.Current.Session["mydata"]
you can use TempData["name"] for sharing data on different actions in a controller. Remember once value is retrieved, it will delete the data but you can use .Peek and .Keep method functionality to store its value

Accessing Controller Properties from a View

I have a User object on a Base controller, this is the standard type of User object you have with the .Net Membership Provider. I need this is decide if users have access to actions, views, and so on.
I am having a problem whereby I want to display user information on the Masterpage. Like a login view from WebForms. I tried to access the User object from the Masterpage but I can't.
So:
Am I breaking the separation of concerns by checking if the user is logged in on the view (simple if statement which changes what is displayed).
Can I simply access the base controller namespace to access this property or is there something wrong with that? When do the controllers get initialised?
As I write this I consider that having my base controller have this property might be a bad idea on the first place.
AGHH!! How would you handle checking user information to change the Masterpage.
Use this:
<% var user = ViewContext.HttpContext.User; %>

ASP.Net MVC & Memberships

I would really appreciate some feedback on what I am trying to achieve:
The problem:
I would like to authorize a user of my application to a single action on the controller. For e.g.: a user can perform the "save" action on my controller class if he has the required authorization.
In the project I am working on, the creation of roles & their authorization is done by the client deployment team & not in my control. So, I program to a "control point" which can be assigned to role/user, while my application needs to only check that control point.
How do I get a control point concept into ASP.Net MVC? More specifically, how do I enable/disable buttons on the View based on the user permission on the controller?
My solution:
Ref.: http://weblogs.asp.net/fredriknormen/archive/2008/03/12/asp-net-mvc-framework-2-interception-and-creating-a-role-action-filter.aspx - as a starting point
Instead of creating a role filter as explained in the link above, I would have a ControlPointFilter class which would get the model & do the authorization check.
The trouble I have is in the View class & I am currently passing the control point collection to which the user has access in the ViewData[] collection.
In the View class, I am checking if the related control point is present in the ViewData collection (which I don't like - want to keep the code to a minimum in the View class)
The other issue is - while the actual control point name is being set in the attribute to the controller class, where/how can I pass these attributes to the view & yet keep the view clean?
Hope that helps & appreciate your time/effort to answer this!
Sunny
One possible solution to this is to translate control points into view attributes in your controller actions (perhaps these are the same things, though, it's not clear from your question). The idea would be that your control point would translate into meaningful view directions such as "AllowEdit", "AllowSave", "AllowDetailedView", etc. These would become entries in ViewData.
Use a base controller class to extend Controller and give it a ControlPoint collection. Have your filter populate this collection in the controller. Have the base controller OnActionExecuted method use this collection and, in the case of a ViewResult, populate the ViewData with the appropriate values for the collection of view directives. Individual controller actions could also use the ControlPoint collection to determine whether they need to provide data for individual views based on whether the view will render extra data or not.
In your view, rely not on the control points themselves but the view directions determined by the base controller. This way you've decoupled the views from the control point logic. Views only operate on view data in ways that are meaningful to the view, not on permission-based data that have meaning in the context of the application. The view won't care how or why the particular directive gets set, it only needs to render appropriately based on the value of the directive.
Hmm, could you not simply create a templating system, to assign roles to users? I.e. create a user template "Power User" that has the roles "CustomerService" and "ConfigurationEditor", and then use the role system as pr usual (i.e. Roles.IsUserInRole(username, rolename))?
For actions, you then use
[Authorized(Roles="CustomerService,CustomerServiceAdmin")]
public ActionResult Edit(...)
{
}
For views, you use
<% if (Roles.IsUserInRole(Context.User.Name, "CustomerService")) %>

Resources