Several Shared layouts for several sidebars - c#

So I'm new to MVC 4 and I'm currently contemplating on what should I do.
CURRENT CODE
I made several SHARED layouts for each type of user. So I now have, _AdminLayout.cshtml for the Admin's sidebar, _FacultyLayout.cshtml for Faculty, and _StudentLayout.cshtml
PROBLEM
I have several types of users: Admin, Student, and Faculty. The content of the sidebar changes depending on which type of user is logged in.
Are there any other solutions for this?
I was planning to put all the sidebars in one SHARED LAYOUT but MVC 4 doesn't have Controllers for Shared Layouts unlike in Web Forms Master Pages, there is a Codebehind file. I'm just trying to shorten my code and lessen the redundancy between the 3 SHARED LAYOUTS that I currently have.

You can have one single layout and use #Html.Action() to render the sidebar as a partial view depending on the role of the user. This could go in a BaseController from which all other controlles inherit, or in a separate controller (say) LayoutController
[ChildActionOnly]
public ActionResult SideBar()
{
var role = ... // your code for getting the users role
if (role == "Admin")
{
return PartialView("_AdminSideBar");
}
else if (role == "Faculty")
{
return PartialView("_FacultySideBar");
}
else if ..........
}
and then create a associated partial views _AdminSideBar.cshtml, _FacultySideBar.cshtml etc.
Then in the Layout Page
......
<div id="sidebar">
#{ Html.RenderAction("", ""); }
</div>

Related

Can I Display User Specific Data throughout the site without adding to each view model

I have a site (MVC5) with a partial that is a header. This header displays the users name, and a logo of the organisation that they represent.
Each page also has a ViewModel of page specific data.
Is there any way I can have this Partial rendered on each page from a common model / object behind the scenes, or do I need to add my 'userheader' viewmodel to the viewmodel on each page?
You can get your requirement done through ChildActionOnly, lets say -
[ChildActionOnly]
public ActionResult LoggedIn()
{
// create your User View Model and pass it to Login Partial View
return PartialView("_LoginPartial", user);
}
Now create a Partial View with a stringly typed model what you are returning from the controller action above.
And in your Layout you can get the partial view like shown below -
#Html.Action("LoggedIn", "ControllerName")
In this way there is no need for you to include the same models across different views.

Multiple Views for one ViewModel on a CreateCar Wizard

I have a wizard with 5 steps, where in each step I get information from the user for his car sale. First it's the operation type (Sale, Rent), second is the Category (Car, Truck, Boat), third is the details of the item (Make, Model, Version), four is the extras and five is the member address.
Each step list of options is build using #Ajax.ActionLink and send the result to a specific DIV in the following master page (Operations -> Category -> Ad -> Extras -> Member -> Create):
#model Heelp.ViewModels.CreateAdViewModel
#using (Html.BeginForm(MVC.Ad.Create(), FormMethod.Post, new { id = "createAdForm" }))
{
#Html.AntiForgeryToken()
<div id="operation">
#{ Html.RenderAction(MVC.Ad.CreateAdOperation()); }
</div>
<div id="category"></div>
<div id="ad"></div>
<div id="extras"></div>
<div id="member"></div>
<input type="submit" value="Create" />
}
This master page has the "master" ViewModel "CreateAdViewModel" that will receive all the information from all the steps, creating all the "inputs" to be sent to the CreateAd Action.
What I have now is a ViewModel for each step:
public class CreateAdOperationViewModel
{
// Operation Fields
}
public class CreateAdCategoryViewModel
{
// Category Fields
}
public class CreateAdViewModel
{
// Common Ad Fields
}
public class CreateAdCarViewModel : CreateAdViewModel
{
// Car View Model Fields
}
The main problem is to know if this solution makes sense because has far has I know, each View should have his own ViewModel, but I need to submit a master ViewModel based on diferent Views, each one with its own ViewModel.
Thank you for your time.
You can share ViewModels across Views, on the basis that these Views need access to the same data. If the shared data is only partial, and not the entire view, you can have separate ViewModels (one ViewModel per View) with a shared "context" property that contains the shared data.
Here is an example article that shows how to do that: http://blog.bitdiff.com/2012/05/sharing-common-view-model-data-in.html
Good luck!

How to use multiple Layout in MVC 3?

I've four kinds of user (Customer, Admin, Manager, teacher) that can use my future ASP Web Site... And so for each of them I have to create different interfaces...
And so my questions:
Is this correct to use different Layout in MVC 3 ? If not what can I use for my problem ?
If it's correct how to use different layout in MVC 3 ? Can you give me one or more example please ?
I would create different _Layout.cshtml pages for each user category and put the _Layout selection logic in _ViewStart.cshtml page.
[Because the _ViewStart.cshtml allows us to write code, we can optionally make our Layout selection logic richer than just a basic property set.]
http://weblogs.asp.net/scottgu/archive/2010/10/22/asp-net-mvc-3-layouts.aspx
You can show the pages in different ways by testing what kind of user it is
In my _Layout.cshtml i have this:
#if (Request.IsAuthenticated && HttpContext.Current.User.IsInRole("Interviewer"))
{
<script type="text/javascript">
$("#logindisplay").show();
</script>
<li>#Html.ActionLink("Forside", "Index", "Home")</li>
<li>#Html.ActionLink("Spørgeskema", "Index", "Survey2")</li>
<li>#Html.ActionLink("Brugere", "Index", "UserAdministration")</li>
<li>#Html.ActionLink("Statistik", "Index", "Statistik")</li>
<li>#Html.ActionLink("Vagtplan", "Vagtplan", "Statistik")</li>
}
#if (HttpContext.Current.User.IsInRole("Respondent"))
{
<li>#Html.ActionLink("Gammelt spørgeskema", "Index")</li>
}
And so on.
You could create different DisplayTemplates for each kind of role and display these based upon which role the user has.
To manually assign Roles to different users, use ASP.NET Configuration
From there, you can create your roles and manage users.
You do not want to do this in the long run, if you get a lot of users on your site. Instead, when they create an account, you would want to assign their role automatically.
You can do this in your AccountController, for instance like this:
if (createStatus == MembershipCreateStatus.Success)
{
Roles.AddUserToRole(model.UserName, "Respondent");
} ....
Your model could have the Role property instead of hardcoding it.
I use 2 Layouts in my applications - Master (for all users) and Admin (for admin team). The only difference is in decorations - Admin has no banners, logos, etc...
So, it is up to you to use several. But I'd stay with one for Customer, Manager and Teacher. Use different CCS files for them to make appearance unique
I found this answer great. Adding to it, if you want use different layout based on the controller name then try editing method like below:
public static string LayoutHelper(RouteData data, string defaultLayout = "")
{
if (data.Values["controller"].ToString() == "client")
return "~/views/shared/_Layout2.cshtml";
return defaultLayout;
}
Client Controller index view
#{
Layout = HtmlHelper.LayoutHelper(Request.RequestContext.RouteData, "~/views/shared/_layout1.cshtml");
ViewBag.Title = "Clients";} <h2>This is my view</h2>
And at last new Layout2.cshtml
<!DOCTYPE html><html><head> <meta name="viewport" content="width=device-width" /><title>#ViewBag.Title</title></head><body> This is my Layout2 <div> RenderBody()</div></body></html>

Multiple access control on a web page - C#

In my company we're currently working in our portal. It will be something like a social network.
I'm working on the "profile" part of the portal.
I was wondering, as I'm new to C#, how can I implement a "see-only-what-i-let-you" functionality.
Take for instance Facebook. There you can show only parts of your profile to some people, other parts to other people, you have full acess as others may have no acess at all.
That's precisely what I need to implement.
We're working with MVC3/jQuery1.5/WCF.
One option would be to split your view up in to child actions:
#{Layout = "~/Views/Shared/Layouts/MasterLayout.cshtml";}
<div class="splitter">
<div class="left-column">
#Html.Action("Navigator")
#Html.Action("MyPosts")
</div>
<div class="main-content">
#Html.Action("RecentStories")
#Html.Action("Adverts")
</div>
</div>
Then in your controller each action decides if the current user can see this piece of content, e.g.
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult RecentStories()
{
if(current_user_cannot_access_this_content())
return View("BlankView"); // Might want to render some place holder content
// Setup necessary view data by pulling back content from the database.....
return View(); // Render the /Views/<controller>/RecentStories.cshtml view
}
Try to cache user permission data across child actions if possible (depends on how your calculation of what a user can see works).
This code is assuming all your actions are running off the same controller. You can hit a different controller for a child action just by passing the name of the controller as the second parameter.

Asp.net MVC - Render a partial View From an Area

I've created an area that will handle our some generic things across all our development products, just as log ins, HTML helpers, etc. Inside the area, I have a partial view that I'm attempting to reference outside of the area. I've registered the area with
public class Routes : AreaRegistration
{
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Common_default",
"Common/{controller}/{action}/{id}",
new {
controller = "Account",
action = "Index",
id = UrlParameter.Optional
});
}
public override string AreaName
{
get { return "MvcCommons"; }
}
}
And now in the regular project, I'm trying to reference a view in the MvcCommons area...
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>TestGrid</h2>
<% Html.RenderPartial("jQGridTable", ViewData.Model); %>
But I keep getting that the view isn't found. Before, while creating the MVC Commons project, I was getting view errors, but the errors told me that it looked in both the area folders and the default view folders. This time, I'm only getting the default folders. Is there any way to accomplish this?
Thanks everyone!
I haven't actually had to do this, but at a guess I would assume you should use Html.RenderAction() instead, something like Html.RenderAction("action", "controller", new { area = "Area", model = ViewData.Model }).
model will have to be replaced with the name of the action's parameters, but that should work.
edit this will require a controller and view setup for each action though.
An important thing to remember is that when using RenderPartial you use it in the context of the current action.
As your action isn't in an area it will only look in the View/ folder for the controller the action belongs to then the shared folder.
Any views you wish to share between areas and controllers and have available at the route should be the root View/Shared folder. Really if the view is callable as a partial like that there is probably little reason for it to belong to an area.
You can call into area when you want to render actions rather than partials - which then changes the context of the current action to the action you call into thereby allowing you to then return views within that area.
The Default ViewEngine looks for the Views inside the same area (or root) folders where the user control is referenced. If you want to create a custom way to use or store views, I suggest you to create a custom ViewEngine. Please take a look at this example: Implement Theme Folders using a Custom ViewEngine

Categories