Working with Collections containing Collections in Asp.Net MVC - asp.net

Looking for some guidance on this issue (below is a parallel example):
I have a view in which I need to display a list of basic user information (e.g. First Name/Last Name) per row. In addition, I need to provide a list of check boxes for that represent permission levels for each user. The list of possible permissions is the same for everyone; however, needs to be dynamically driven by the database since different permission sets may be added or removed.
So...I have a list of users, and a common yet variable list of permissions that needs to be tracked per user.
What's the best way to manage this from an object bind standpoint in a ASP.Net view?

I've solved a similar scenario using EditorTemplates
You could have a Users collection in the AssignPermissionViewModel, and a Permission collection in each user (UserModel). Then in your AssignPermission view, you should render the users editor:
#Html.EditorFor(model => model.Users) //here model is a AssignPermissionViewModel
And inside the user editor template you should render the permissions template:
#Html.EditorFor(model => model.Permissions) //here model is a UserModel
This way you avoid having foreach loops all over your AssignPermission view, and you could re-use any editor in another view... (although these are very specific)
NOTE: It would be more appropriate to use a display template instead of an editor template to display the users information, since you're not going to edit any user in this view, check this out: ASP.NET MVC 3 - Partial vs Display Template vs Editor Template

You should create a List of Users in your View Model. A User should be a Class in which you create a property that is a list of Permission Levels, so in your View you sould call something like this:
<ul>
foreach(var user in Model.Users)
{
<li> user.FirstName...
<ul>
foreach(var permissions in user.Permissions)
{
<li> permission.SomeProperty </li>
}
</ul>
</li>
}
</ul>

Related

How do you completely hide an element from a user based on their ASP.NET Identity Role?

Goal: Hide certain elements like page links from users based on their role in ASP.NET Identity.
What I have tried: [Authorize(Roles = IdentityHelper.Administrator)]
(This does restrict access to certain elements if you put the annotation over them, like pages, but it doesn't hide the element itself. I want it to do both.) Its not entirely critical that I hide these elements from the user since they're already restricted, but it would make my website look better to the users.
(IdentityHelper is just a helper class that sets up all the details about the administrator role)
Code Example:
//Restricts access, which is good, but does not completely hide elements from user.
[Authorize(Roles = IdentityHelper.Administrator)]
public async Task <IActionResult> Edit(int id)
{
//get pixel art with corrosponding id
PixelArt p = await PixelDBManager.GetSinglePixelAsync(id, _context);
//pass pixel art to view
return View(p);
}
Should I perhaps switch to Claims or Policy based identity instead of Roles or can I stick with Roles to solve this particular problem?
You can use User.IsInRole() in your Razor template.
#if(User.IsInRole(IdentityHelper.Administrator))
{
<h1>I'm an administrator</h1>
}

How to edit or Is it possible to edit views from database and replace them with custom labels or text boxes based on condition?

I have been following this article for rendering view from database and then using VirtualPathProvider class to register the route.
My main requirement is such that i want to render the same view, based on condition, so that it will open once in Edit mode and once in Read only mode.
Now i am trying to achieve this beacuse i do not want to change the views twice(once for edit and once for readonly) if i have to change the page, means adding new textboxes(edit mode) or labels (readonly mode) then it would mean to actually manage two views or more when the application expand and became more complex.
Saving the view in database as a string is option that i found on internet but then it is not possible to manipulate string in c# to add textboxes or labels dynamically.
So is it possible to achieve this kind of behaviour, I know many of us do not want to manage multiple views, also we would have over crowded solution folder for views if we add views as file in filesystem.
Any kind of opinion(help or criticism) is welcome.
EDIT
Using If Else code block will result in same effect of managing multiple html's
EDIT 2
Code?, i only want to know the implementation, Instead of saving a view hardcoded in DB table, i want to be able to change the view according to the condition.
So my requirement is not only to serve the view from DB but to be able to change the View on demand, Hence making it very dynamic.
Any way i am providing a small implementation for this. without VirtualPathProvider Class
Let's keep things simple, I am querying the database using EF and passing the Model to View.
So in Controller i am using following query.
public ActionResult DynamicView(int id)
{
var abc= db.DummyTable.Where(c => c.ID == id).ToList();
return View(abc);
}
Then in View
#model IEnumerable<Project.Models.DummyTable>
#foreach (var item in Model)
{
<tr>
<td>
<label>#item.Name</label>
</td>
<td>
<label>#item.Class</label>
</td>
<td>
<label>#item.RollNumber</label>
</td>
</tr>
}
So instead saving my whole view in the table, I want the view to be able to change if it is in Edit mode like I would want to have Textboxes instead of Labels.
Thank you

How to make a list of links that dynamically updates from a Database?

I am re-developing my website in ASP.NET 5, with MVC 6 and EntityFramework 7. It is a reference website for LEGO Collectors. I am Trying to, on the "browse the database" home page, have a list of all years that products have been released. I have developed one, but I am trying to figure out how to link to each year View in the "Browse" Controller, and have the link names be the years.
Example:
2014
2015
2016
Is what my page is like now, but dynamic. I want these years to appear as links, and link to the section for each year in the Controller.
Here is my current code:
<ul class="browse-years">
#foreach (var item in Model.Select(c => c.YearFrom).Distinct()) {
<li>#item</li>
}
I hope you can help with this. Thank you.
Jarod
Owner of UltimateBrickReference.com
Inside your LI element, use an Html.ActionLink helper to create your link:
<li>#Html.ActionLink(item.ToString(), "ListYear", new { thisYear = item })</li>
This will render HTML that looks like this:
<li>2016</li>
The first argument is the link text; if item is not a string, then it must be converted to one. The second argument is the controller action that you want to get control when the user clicks the link. The third argument is an object containing a property that stores the value the year (or item or item.year or whatever), so the controller knows which year to display data for.
Then, in your controller, write an action that gets the data to be displayed and transfers control to a view that will display that data. It will start out something like this:
public ViewResult ListYear(object year)
{
return View();
}
You can add the code to extract the year from the object, retrieve it from the database, and then pass it to a view that you will create to display the passed data.
use this:
<li><a asp-controller="Product" asp-action="Display" asp-route-id="#ViewBag.ProductId">#item</a></li>
this will give you the following:
View Details
So change the asp-controller, asp-action and asp-route-id based on what you want. If you want any help please let me know

In ASP MVC is there a way access a session state from a shared view such as _Layout.cshml

I'm trying to make it so the links that display on the nav bar from the _Layout view change depedning on whether you are logged in. This is using a SessionStateRepository which I use by initializing it in my controllers.
On the layout page I want to be able to check if
state.GetLoginState().email = "anon"
This is so I can change if the login button is there or not. I just can't find a way to use it on a shared view which goes on all pages.
Well, using session state with MVC is a topic of religious debate (for number of good reasons ) and you should definitely read up on that.
But to answer your question, with traditional session class, you can do this
#if (HttpContext.Current.Session["email"] == "anon")
{
<span>Value1</span>
}
else
{
<span>Value2</span>
}
you will have to devise specific implementation on the similar lines based on your repository

Changing menu links, if user is authenticated or not

I need to change the menu links on my website (and leave the same items names) depending on the user is a guest, or authenticated user.
What's the standard way to do it ?
thanks
You cannot dynamically change a menu item's path, because menu items are cached.
Still, AFAIK, there are two ways to get what you want. Both methods require you to create your menu items with hook_menu in a custom module (not from the Menu UI).
The first method is to create two menu items with identical names and set the access rules so that one is only available for logged guests, the other for authenticated users. Since Drupal will only show menu items that the user is allowed to access, only one will show up at any given moment. In Drupal core, you can see how the user module creates a menu item for anonymous users by looking at the /user/login path in user_menu().
The second method is to create a single menu item and check in the menu callback if the user is logged in. If the user is logged in, you serve one page, if not you serve another. In Drupal core, the /user path works like this. See user_page to see how the code works.
You can dynamically change a menu item's path - see hook_translated_menu_link_alter.
This hook is called before every menu item is rendered IF it has the property ['options']['alter'] = TRUE.
You can set this property to menu items using hook_menu_link_alter.
Example code would be:
function MY_MODULE_menu_link_alter(&$item) {
$item['options']['alter'] = TRUE;
}
function MY_MODULE_translated_menu_link_alter(&$item, $map) {
if($item['mlid']==89) {
$item['link_path'] .= 'my-new-path';
}
}
Instead of altering the link, you coudl create the menues twice: once with the links for regular users and once with the links for registered/admin/... users
You can put a menu into a block and set it to only allow registered users to see the one block and non-registered users the other block. Either by selecting the proper radio button from the Drupal menu within the block creation form or via PHP that will evaluate and depending on it's return value (TRUE/FALSE) displays it. I suggest to go with the first approach.
You can change the menu by using a combination of nodeaccess module and linking to the corresponding pages.
For example, by default guest users cannot access /logout. If you create a link in a menu to logout, it will only display if a user is logged in. With nodeaccess, simply create a node, visit the grant tab and uncheck/check "authenticated users" or "anonymous users" for that node.
http://drupal.org/project/nodeaccess
Cheers,

Resources