Set Layout for Single paged application in ASP.NET MVC - asp.net-mvc

I'm new to MVC and trying to create a single paged application.
My Content in _Layout.cshtml
<section class="content-wrapper main-content clear-fix">
#Html.Action("Index", "MenuNavigation", "U01")
#RenderBody()
</section>
Note: #Html.Action("Index", "MenuNavigation", "U01") is the place where I'm rendering my dynamic Navigation menu from database(will load only once from DB)
Below is my _MainLayout.cshtml that uses _Layout.cshtml as master page
#{
ViewBag.Title = "";
Layout = "_Layout.cshtml";
}
<div id="MainPageContent">
#RenderBody()
</div>
Here is my Home\Index view will looks like
#{
ViewBag.Title = "Home Page";
if (ViewBag.IsRequestFromLoginPage !=null && ViewBag.IsRequestFromLoginPage)
{
Layout = "~/Views/Shared/_MainLayout.cshtml";
}
else
{
Layout = null;
}
}
#Html.AntiForgeryToken()
<h2>Home</h2>
here is the respective Home controller
public ActionResult Index()
{
ViewBag.IsRequestFromLoginPage = TempData[Constants.TempData.IsUserFromLogin];
TempData[Constants.TempData.IsUserFromLogin] = false;
return View();
}
When user logged-in to my site I wanted to render my Home\Index and load my Nav Menu(partial content) only on the first load.
If User select any of the menu item, I'm doing AJAX call to update the MainPageContent in _MainLayout.cshtml by this way I'm trying to create the single paged application but problem is when User refresh the page from browser URL. For example: If User is in "MyApp.com/Home" and refresh the browser it causes my application looses its _layout (render only home content) because of the ViewBag.IsRequestFromLoginPage check in my Home page.
Not sure is this the correct way to achieve this. Is there any alternative to do so. Any help will be appreciated. Thanks!
Here is how my Layout is looks like>
#Daniel

Your code is a little bit redundant, why do you have #RenderBody() in _MainLayout.cshtml if you say its master layout is _Layout.cshtml which also calls #RenderBody? instead of using #Html.Action and #RenderBody() use Html.RenderAction (When calling a differente method that's not index) and don't specify a Layout for your that view, in that same way, get rid of all the validations to see if it comes from the login page or not, note that Index method always enters by default so there's actually not even a need of calling any type of HTML action if you're accessing your Home Controller, you could leave your main layout like this
<section class="content-wrapper main-content clear-fix">
<div id="MainPageContent">
#RenderBody()
</div>
</section>
and your Index view like this:
#Html.AntiForgeryToken()
<h2>Home</h2>
In a different ActionResult method you can load the same view as Index like this:
public ActionResult update(){
return View("Index");
}
You'd then make the AJAX call to fill the "MainContentPage" div with that method instead of "Index".

Related

Layout page not loading in asp.net mvc

I've created a strongly typed view selected a layout page
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_xyzLayout.cshtml";
}
but this layout page never gets loaded when I run the page
Layout Snapshot
#RenderSection("scripts", required: false) u can call this code inside the layout page
Then u call every page #Rendersection scripts{
Your scripts}
#RenderSection("styles", required: false) also
http://www.dotnettricks.com/learn/mvc/layouts-renderbody-rendersection-and-renderpage-in-aspnet-mvc
Refer this page
Ensure the controller routing to the page uses a View method call. For example
public ActionResult Details(int custid )
{
Customer customer = new Customer(id =2, Name = "Dipo")
return View(customer);
}

PartialView redirects rather than inserts

I have a form and a partial view on my razor page, the idea being that if I change the dropdownlist, the Controller does some work and sets a ViewBag.ShowAlert (bool) that triggers the partial view to be displayed.
While this works, instead of just showing the code within the partial view, the partial view shows as a new view rather than on the same view.
Any idea why?
The view looks like this
#using (Html.BeginForm("AlterVote", "ChangeVoteType"))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h1>New voting preference</h1>
<hr />
<p>Please select the type of vote you wish to change to #Html.DropDownListFor(model=>model.SelectedType, ViewBag.myList as SelectList, "Voting type", new { onchange = "this.form.submit();"})</p>
<div id="partialDiv">
#if (ViewBag.ShowAlert)
{
#Html.Partial("VotingChange")
}
</div>
</div>
}
The controller handling the HttpPost is this
[HttpPost]
public PartialViewResult AlterVote(Dropdown dropType)
{
ChangeBoilerPlate(dropType.SelectedType);
dropType.CurrentType = VoteTypeNames[(int)HomeController.VoterModel.CurrentVoteType];
return PartialView("VotingChange", dropType);
}
I'm guessing that this is down to the initial view being a form, so the partial gets confused as to where to insert the view.
If I understand correctly, by the partial view shows as a new view you mean it comes with a html tag, body and the full layout again. To solve this, you need to set up the layout to null inside your partial view, like so:
#model YourNamespace.Dropdown
#{
Layout = null;
}
<!-- partial view html below -->
<div>
</div>
The div tag is just to illustrate.
While this might solve your problem, you might want to load the partial view without reloading the whole page again. This is possible using ajax, like so:
Main View
#using (Html.BeginForm("AlterVote", "ChangeVoteType"))
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h1>New voting preference</h1>
<hr />
<p>Please select the type of vote you wish to change to #Html.DropDownListFor(model=>model.SelectedType, ViewBag.myList as SelectList, "Voting type", new { id = "vote"})</p>
<div id="partialDiv">
</div>
</div>
}
<script type="text/javascript">
$(document).ready(function () {
$('#vote').change(function() {
var selectedType = $(this).val();
$.post('yourserver/YourController/AlterVote', { "SelectedType": selectedType })
.done(function (data) {
$('#partialDiv').html(data);
})
.fail(function () {
console.log('Whoops, something went wrong!!!');
});
});
});
</script>
So I just added a javascript to listen to that same change event on your dropdrown, but instead of submitting the form, I just use ajax to load the partial view html without reloading the entire page.
Just fix the URL and remember to set up layout to null in your partial view. Also, you might want this javascript in a separate file, thus loading it with bundles.

MVC Entity Framework Razor Issue

I have to following code and there's a problem and I can't figure out what's the problem. Well, I have two ideas about the place where the problem may appear but I can't find a solution.
The problem is that my layout is rendered twice.
Layout.cshtml
<div id="container">
<div id="left_side"> #RenderPage("left_side.cshtml") </div>
<div id="center_side"> #RenderBody() </div>
<div id="right_side"> #RenderPage("right_side.cshtml") </div>
</div>
left_side.cshtml
#if (ViewBag.LeftColumnVisible == true)
{
#Html.Action("GetCategories", "Products");
}
GetCategories method from Products controller
public ActionResult GetCategories()
{
List<Categories> categories = db.Categories.ToList();
...
return View();
}
GetCategories.cshtml
#foreach (System.Collections.DictionaryEntry de in ViewBag.LeftColumnContent)
{
<div> #((Ads.Models.Categories)(de.Key)).Name; </div>
}
It enters the get categories and renders the content.
The problem for rendering twice may be at this line
#Html.Action("GetCategories", "Products"); or when it calls View(). If I comment the line, my layout will be rendered only once.
I'd say there are a couple of issues with your code. First of all, if left_side.cshtml/right_side.cshtml are partial views then you want to be using
#Html.RenderPartial("view")
to render them and not #RenderPage - although #RenderPage will work it's better from a readability point of view to understand exactly what the type of view it is you are working with.
Secondly, if your GetCategories view is a partial view you want to be returning a PartialView and not a View i.e.
public ActionResult GetCategories()
{
...
return PartialView();
}

MVC 3 show hide Partial Views in jquery UI tabs

In our application we are using Tabs to display the information for example contacts, in this tab the user can switch between view contacts and created contact. When the user clicks on ‘Create’ I want the partial view changed to CreateContact within the same tab. What is the best way to show hide a Partial Views in jquery UI tabs? Should I use Ajax code to do this?
View
<div id="tabs">
<ul>
<li>Claim</li>
<li>Products</li>
<li>Contact Us</li>
</ul>
</div>
Controller
public ActionResult GetContact()
{
return PartialView();
}
public ActionResult CreateContact()
{
return PartialView();
}
Partial View
<li>#Html.ActionLink("Create", "Test", "Home")</li>
Thanks
Yes, you can use AJAX. That is in case you don't want to load all partial views at once.
If it doesn't matter, you can just render them at once:
<div id="tabs-1">
#Html.Partial("GetClaim")
</div>
<div id="tabs-2">
#Html.Partial("GetProduct")
</div>
<div id="tabs-3">
#Html.Partial("GetClaim")
</div>
jQuery hides the elements that are not currently visible and will manage the switching automatically.
You can use an Ajax.ActionLink() - http://msdn.microsoft.com/en-us/library/dd493106.aspx
This will asynchronously submit your form to your controller method. If you set the AjaxOptions.InsertionMode to be AjaxOptions.InsertionMode.Replace then it will replace the partial view content with whatever you return from the controller. Then, you just need to return the GetContacts view in the creatcontacts controller action, as below:
[HttpGet]
public ActionResult GetContact()
{
return PartialView(RetrieveListOfContacts());
}
[HttpPost]
public ActionResult CreateContact(StronglyTypedContactModel contact)
{
if (ModelState.IsValid)
{
// .. write your contact here
return PartialView("GetContact", RetrieveListOfContacts());
}
else
{
return PartialView(contact);
}
}
EDIT
Also, you can specify that it be a GET request in the HttpMethod of the AjaxOptions, so as not to require form (as I originally assumed you did).

ASP.NET MVC RenderAction re-renders whole page

How do I prevent renderaction from rendering the masterpage and giving it back to me? I only want it to render 1 section, for eg.
The controller
public ActionResult PaymentOptions()
{
return View(settingService.GetPaymentBanks().ToList());
}
The PaymentOptions View:
#model IEnumerable<Econo.Domain.PaymentBank>
<h2>Payments</h2>
<!-- Stuff here -->
The View
<div class="grid_10">
</div>
<div class="grid_14">
#{Html.RenderAction("PaymentOptions", "Administrator");}
</div>
In grid_14, the header, footer and everything else gets rendered. Is there a way to prevent this?
public ActionResult PaymentOptions()
{
return PartialView(settingService.GetPaymentBanks().ToList());
}
In Razor, partial views and full views have the same extension, so you need to explicitly use the PartialViewResult result type to specify a partial view.
This:
return View(settingService.GetPaymentBanks().ToList());
Has to use the overload so you can specify a master:
return View("PaymentOptions", "", settingService.GetPaymentBanks().ToList());

Resources