Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
We have recently decided to switch from asp.net webforms to asp.net mvc for some new projects. As a long time webforms developer I have watched and read quite a lot of introductory tutorials and how to switch articles and video's. However some things still bug me (no pun intended) a litte bit. And I'm hoping I could get some answers from the community here.
First, we have a cms-system that we are required to use for a client. In the system they obviously manage the navigation (menu) for the webproject. My first question is, how would I go about to adding this dynamic navigation to all the pages (views). In webforms I would simply create a custom user control and throw it onto the masterpage or template. I suspect the answer to be viewmodels? Or partial views?
The second question is related. Often we would have a few pages that show some news for example in a side panel. Others would not. Would I create a different viewmodel for the different scenarios, work with sections?
I don't expect a definite answer, but more some guidelines/best practices. Any input is appreciated.
Your question is extremely broad so I'll only give a high level way of achieving this.
For the menu system you can create two Div elements, one for the menu and one for the content. The menu div should contain an Action that calls JavaScript to replace the content of the main Div with a Partial View returned by your Controller.
In your _Layout page you can something like this
<body>
#Html.Action("RetrieveSideBar", "SideBar", new { area = "" })
<div id="mainScreenDiv">
#RenderBody()
</div>
</body>
RetrieveSideBar renders the menu items
public class SideBarController : MyControllerBase {
/// <summary>
/// Retrieves the side bar.
/// </summary>
/// <returns></returns>
public ActionResult RetrieveSideBar() {
var menuItems = new List<MenuItem>();
return PartialView("_SideBar", MenuItems());
}
private List<MenuItem> NotAuthenticatedMenuItems() {
var menuItems = new List<MenuItem>();
menuItems.Add(new MenuItem() { Title = "Register Firm", ActionUrl = Url.Action("Create", "FirmPreRegistration") });
return menuItems;
}
}
Where MenuItem is
public class MenuItem {
public string Title { get; set; }
public string ActionUrl { get; set; }
}
_SideBar renders the menu as follows
#model List<MenuItem>
<ul class="nav nav-sidebar">
#foreach (var menuItem in Model) {
<li class="text-info leftMenuHeading ">
<a href="#" onclick="NavigateTo('#menuItem.ActionUrl')">
<span>#menuItem.Title</span>
</a>
</li>
}
</ul>
Note that clicking on a menu item calls NavigateTo which is defined as follows in the '_Layout' page
function NavigateTo(view) {
$.ajax({
url: view,
type: "GET",
cache: false,
success: function(data) {
$('#mainScreenDiv').html(data);
});
}
This creates an Ajax based navigation system that will replace the content in the page with the navigated page, note that Action methods need to return PartialView or else _Layout renders again.
My first question is, how would I go about to adding this dynamic navigation to all the pages (views). In webforms I would simply create a custom user control and throw it onto the masterpage or template.
Asp.Net MVC has something similar - _Layout.cshtml. By default it is inside Views/Shared folder and it is like master page for all pages. You can generate your dynamic menu in following way
public abstract class BaseController : Controller
{
public YourMenuModel YourMenuModel { get; set; }
public BaseController()
{
this.YourMenuModel = //load dynamically your menu. For example from database
ViewBag.MenuModel = this.YourMenuModel ;
}
}
Inside _layout view you can get your menu model and render in any way
#{
var YourMenuModel = (YourMenuModel)ViewBag.MenuModel;
}
Often we would have a few pages that show some news for example in a side panel. Others would not. Would I create a different viewmodel for the different scenarios, work with sections?
I would create partial view for news and put it inside some views
#Html.Partial("_YourNewsPartial")
Related
I use view components in my projects. Sometimes, I need to use the same view component as various styles. I researched a lot but I don't find a solution.
The code below works fine but when I do like this, I couldn't use it the way I wanted.
View component class:
public IViewComponentResult Invoke(BlogSidebarViewModel vm)
{
vm.BlogTags = _uow.BlogTag.GetAllByPriority(true,vm.LangId,vm.WebsiteId);
vm.BlogCategories = _uow.BlogCategory.GetAllByPriority(true,vm.LangId,vm.WebsiteId).Include(p=>p.BlogTag);
vm.RecentBlogs = _uow.Blog.GetAllByEnabledDate(true,vm.LangId,vm.WebsiteId);
//return View(vm); //For Default Blog Sidebar View Component
//return View("RedComponent", vm); //For Red Blog Sidebar View Component
//return View("GreenComponent",vm);//For Green Blog Sidebar View Component
}
But, when I write the following code, I get an error.
#await Component.InvokeAsync("BlogSidebar/RedComponent");
or
#await Component.InvokeAsync("~/Views/Shared/Components/BlogSidebar/GreenComponent.cshtml");
I want to use view components in various views. How can I do? Can I do it?
EDIT
Can I use the views of view component at the same time? For example, while I use the "GreenComponent" in the "Blogs/ABC.cshtml" view, I would like to use the "RedComponent" View in the "Blogs/XYZ.cshtml" view.
Please follow the steps below to use View Components:
1.Create GreenComponent.cshtml in folder:Views/Shared/Components/BlogSidebar.
2.Create View Component named BlogSidebar:
public class BlogSidebar : ViewComponent
{
public IViewComponentResult Invoke(BlogSidebarViewModel vm)
{
vm.Id = 1;
vm.Name = "aaa";
return View("GreenComponent",vm);
}
}
3.GreenComponent.cshtml:
#model BlogSidebarViewModel
Name: #Model.Name
4.Index.cshtml:
#model BlogSidebarViewModel
#await Component.InvokeAsync("BlogSidebar",new BlogSidebarViewModel())
Result:
I m working on ASP.NET MVC 4 application.I have a dashboard and my users groups will be based on Windows Domain
So I am using WIndows Authentication for authenticating users.
I created sample applications which uses custom authentication by overrides functions AuthorizeAttribute, ActionFilterAttribute . Is this a good approach ?
Which attribute is best used for authentication ?
I have a dashboard. So I need to show or hide the controls based on roles.
Suppose if there is 3 grids(table), If Admin is logs in, he can able see 3 grids(tables).
But if Support user is log in he can see 2 grids (table) only.
My plan is to create partial views for each grid and so there will be an Action and Controller for each partial view.
There will be a database and in that I will specify the actions which each group can perform. So that I can filter the requests.
2 How can I hide or show the partial views based on roles ?.
I tried some SO links, but all they are talking about 2,3 roles and it was hard coded.
In my case roles may vary and we uses db to set up access for roles.
Thanks in advance.
You can use Following code for role based checking
#if(Request.IsAuthenticated)
{
if(User.IsInRole("Admin"))
{
<Ul Class="SubMenuItem">
<li> this menu item is for Admin role</li>
</Ul>
}
if(User.IsInRole("User"))
{
<Ul Class="SubMenuItem">
<li> this menu item is for User role</li>
</Ul>
}
}
#* For unknown user *#
else
{
<Ul Class="SubMenuItem">
<li> this menu item is for Unknown user</li>
</Ul>
}
Typically you would want to keep your views as clean as possible with little to no logic.
I would suggest moving your role checking logic into a controller action and rendering a partial view based on the users role.
You can use ChildActions and the Html.Action extension method to get this wired up.
From MSDN:
A child action method renders inline HTML markup for part of a view
instead of rendering a whole view. Any method that is marked with
ChildActionOnlyAttribute can be called only with the Action or
RenderAction HTML extension methods.
In your project, create a new Controller called Dashboard and added a single Action called BuildTable.
public class DashboardController : Controller
{
[ChildActionOnly]
public ActionResult BuildTable()
{
if (Roles.IsUserInRole("Administrator"))
{
return PartialView("_AdminTable");
}
return PartialView("_SupportTable");
}
}
Include the following line in the view where you want the dashboard table to appear.
#Html.Action("BuildTable", "Dashboard")
I have done something similar. The way I did it (may not be the best)
is to send a boolean back to the view
in the controller use:
bool showSection1 = true;
bool showSection2 = false;
ViewData["showSection1"] = showSection1;
ViewData["showSection2"] = showSection2;
/// may be better to use a viewmodel here rather than ViewData
then in the view:
#if((bool)ViewData["showSection1"])
{
#{Html.RenderPartial("section1");}
}
#if((bool)ViewData["showSection2"))
{
#{Html.RenderPartial("Section2");}
}
you will need to do the logic to set the boolean the way you want them but this should be a start.
you could also create a static method that returns the role and then get that value directly from the view. this may be bad form though.
#if(AppHelper.GetRole().equals("role1")){
//show the partial
}
then create a class called AppHelper and a method called GetRole that returns the role of the user.
i have created a master page with lots of effort but i am not able to figure out how to make my tab selected based on the user click.
i have used one method to do that but finding very complicated as i have pass a viewdata from each of my controller which i dont like it, below is how i have done code in controller
ViewData["ActiveMenu"] = "Inbox";
and in my master page i have written a jquery like below to make the tab highlighted.
$('#lnkInbox').mouseout(function () {
$('#aInbox').removeClass('aInbox-Hover');
$('#aInbox').addClass('aInbox');
//put hover effect on the selected menu
var activeMenu = '<%:ViewData["ActiveMenu"] %>';
if (activeMenu == "Account") {
$('#aAccount').removeClass('aAccount');
$('#aAccount').addClass('aAccount-Hover');
}});
this is how i am doing but is there any other way i can do that...
please suggest
i have found one good link active menu item - asp.net mvc3 master page
but the answer which is showed there i am not able understand how to i utilize in my code and where to write the code in my project.
Use the answer you found.
To create helper class add new class to you project, i.e. like this
public static class LinkHelpers
{
//copy here the first block of code from the answer
}
Add to your HomeController methods (probably you already have them):
public class HomeController : Controller
{
public ActionResult About()
{
return View()
}
public ActionResult Index()
{
return View()
}
}
Create respective views and add to your master page
<ul>
<li>#Html.MenuLink("Main", "Index", "Home")</li>
<li>#Html.MenuLink("About us", "About", "Home")</li>
</ul>
And finally in your css file declare
.current{background-color:red;}
I have a MVC3 view that enables the user to create a couple different things. Within the parent view the forms to do so are broken up via jquery ui tabs like the following:
<div id="tabs">
<ul>
<li>New Thing 1</li>
<li>Different New Thing</li>
</ul>
<div id="tabs-1">#Html.Action("CreateNewThing", "NewThingController")</div>
<div id="tabs-2">#Html.Action("CreateDifferentThing", "DifferentThing")</div>
<div></div>
</div>
<script type="text/javascript">
$(function () {
$("#tabs").tabs();
});
</script>
Within the partial view I have:
#model NewThingViewModel
#using (Html.BeginForm("CreateNewThing", "NewThingController", FormMethod.Post, new { id = "frmCreateNewThing" }))
{
...
with input fields, a submit button, etc. This seems to work well: it renders everything and posts just fine to the right controller action method.
However I'm now wiring in the validation and I've got an issue.
In the controller it is rendering the view like so:
public ActionResult CreateNewThing(NewThingViewModel model)
{
... initializing model fields, drop downs etc.
return PartialView("CreateNewThing", model);
}
I have a seperate post method like so:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult CreateNewThing(NewThingViewModel newThingViewModel, FormCollection collection)
{
.....
}
Sample Model:
public class NewThingViewModel
{
[Required]
[StringLength(50)]
[Display(Name = "Display Name:")]
public string DisplayName { get; set; }
}
The trouble is, when the page first comes up the fields marked as [Required] through DataAnnotations in the model are showing up red as well as the validation summary showing them invalid when the page initially shows. I.E. it's acting like it's already been posted before the user gets to enter anything on the initial load or even put anything in the text boxes.
I know the first non-post CreateNewThing is firing because I can catch it in the debugger and I know the 2nd one does not on the initial load.
What would cause my validations to fire on the Get?
Is it due to the way Html.Action works and the fact that I'm rendering partial views onto another view?
I'm using UnobtrusiveJavaScriptEnabled and ClientValidationEnabled = true in web.config.
I can't find anyone else that has run into this particular problem. Every other example just seems to work, then again I don't find an example where the view is broken into three partials contained within jquery ui tabs.
How do I fix this?
Options:
Do I need to manually manipulate the Model.IsValid as a workaround?
Use a different mechanism to render the partial views on the parent view instead of Html.Action?
Use some javascript/jquery to catch the validation and stop it?
Don't have method parameters on your GET controller action. You can initialize an empty model and pass it to the view but you dont need a model to be passed into the method
You're passing in an "empty" model (which I assume has default values set for your required properties), when you should be passing in null.
I used the following tutorial to help me build an RSS Reader in my ASP.NET MVC3 Razor application:
http://weblogs.asp.net/jalpeshpvadgama/archive/2011/08/17/creating-basic-rss-reader-in-asp-net-mvc-3.aspx
However, unlike the tutorial example, I want the RSS feed to be displayed on every page, and have therefore added it to my layout file, /Views/Shared/_Layout.cshtml
I currently only have 2 views on my site, and to get the RSS Reader to work on both views I've got the following code in my HomeController:
public class HomeController : Controller
{
//
// GET: /Index/
public ActionResult Index()
{
return View(CT.Models.RssReader.GetRssFeed());
}
public ActionResult About()
{
return View(CT.Models.RssReader.GetRssFeed());
}
}
From my WebForms experience, I would simply add the RSS Reader code in my master page code behind, and it would automatically work on every page.
Is there a Controller for layout pages which allows me to do the same?
How can I get this to work on every call of the layout page, without having to return anything?
EDIT: Following #Sebastian's advice, I've now added this code to a Partial View, removed CT.Models.RssReader.GetRssFeed() from return View() and included this in my layout file:
#Html.Partial("_MyPartialView")
The code in this partial view is:
<ul>
#foreach (var item in Model)
{
<li>
#item.Title
</li>
}
</ul>
However, I'm not getting a runtime error:
Object reference not set to an instance of an object.
It's erroring on the line #foreach (var item in Model)
You have to create a partial view and add functionality there.
Then in your layout, render this partial.
EDIT
Is your partial view really a partial view? The reason I said that is because you have "_" in front of the name which suggests that it might be a layout (might just be a naming convention).
To fix object reference error, you have to add the #Model declaration on top of your partial view.
Hope it helps.
UPDATE
In order to use different model in partial view, you need to explicitly declare which model you are going to use on render partialmethod.
#{Html.RenderPartial("../YourFeed", Model.YourFeedModel);}
Let me know if that resolved your issue.
The new error you are having is due to you not passing a Model to the partial view. You can do this with the second argument of the Html.Partial function...
Html.Partial("ViewName", MyModel);
As I think you are trying to do this in a Layout page you could also consider using a static reference to get your RSS feed. So forget about needing to pass in a Model and in your partial have:
#foreach (var item in RssRepository.GetFeed())
{
<li>
#item.Title
</li>
}
this like to a class something like...
public static RssRepository
{
public static MyModel GetFeed()
{
return new MyModel();//<- return what you would normally pass as a Model for RSS feeds
}
}
Hope that all makes sense