DotNetNuke MVC including cshtml in div - asp.net

First MVC attempt in DNN.
I have a fairly involved index.cshtml that I'd like to simplify by using jquery's
$('#mydiv').load() method.
Currently, in the index.cshtml, I'm having to do a bunch of divs like this (very simple) example:
<div id="dvBands">
#using (var ac = new ArtistListingController())
{
ac.Gets();
foreach (var a in ac.Recordset)
{
<div>#a.ArtistName</div><br/>
}
}
</div>
I tried putting the above code in its own _ArtistListing.cshtml and using
$('#dvBands').load("tabId/#Dnn.ModuleContext.TabId/moduleId/#Dnn.ModuleContext.ModuleId/controller/Item/action/_ArtistListing")
with this in my item controller:
public ActionResult _ArtistListing()
{
return View("_ArtistListing");
}
However, not only does it now display the data, it displays the entire page in the div, including the DNN menu and whatnot.
So, how do I separate out my different database calls and include them in the specified div?

In my index.cshtml ---
#{ Html.RenderPartial("_ArtistListing"); }
It looks for a .cshtml file first in the current path and if it can't find it there, in the Shared folders path.
That's it.

Related

Where to populate multiple dropdown lists

I'm trying to determine the correct approach to populating multiple dropdown lists on a view page of an .net MVC application, which is using angularJS.
In my app, designed as a silo-SLA app. I'm using the angular ngRoute module, and the $routeProvider to describe the multiple HTML pages for a single CSHTML page.
.config(function ($routeProvider, $locationProvider) {
$routeProvider.when('/club', { templateUrl: '/App/Club/Views/MCLView.html', controller: 'mclViewModel' });
$routeProvider.when('/club/list', { templateUrl: '/App/Club/Views/MCLView.html', controller: 'mclViewModel' });
$routeProvider.when('/club/show/:clubId', { templateUrl: '/App/Club/Views/ClubView.html', controller: 'clubViewModel' });
$routeProvider.otherwise({ redirectTo: '/club' });
$locationProvider.html5Mode(true);
});
My CSHTML page is basically empty except for the <div ng-view></div> tag. The routed HTML pages get loaded into the ng-view div.
<div data-ng-app="club" id="club" data-ng-controller="rootViewModel">
<h2>{{ pageHeading }}</h2>
<div ng-view></div>
</div
Each html view page loaded into the ng-view has an associated viewmodel javascript controller.
I started out populating the first dropdown on the html page by using $http.get in the angular controller to get the list data (json) from a server call. Then do a JSON.parse on the result.data and populate the select list control that is defined in the html page.
$scope.refreshColorsDropdown = function () {
var sel = document.getElementById('colorDropdown');
var colors = JSON.parse($scope.mycolors);
angular.forEach(colors, function(color) {
var opt = document.createElement('option');
opt.innerHTML = color.name;
opt.value = color.hex;
sel.appendChild(opt);
});
}
I could continue this approach for each dropdown on my page, creating several server calls to populate all my dropdowns ... but this seems tedious and code heavy.
Would a reasonable approach be to consider building one server calls that returns multiple collections, one for each dropdown, and then I'd parse those to populate all the dropdowns?
I'd like to pre-populate the lists on the server side C# code, however my cshtml files are empty except for the ng-view div, so there's no coding going on there.
So to my question ... if my HTML views contain all the html content, and the cshtml are empty ... what strategy should I be using to populate multiple html list controls from the server side?
Using MVC, you can make a ViewModel that contains all collections needed and return this collection to your Angular Controller.
Your View Model would be something like:
public class MyViewModel
{
public List<ColorModel> Colors{get;set;}
public List<FabircModel> Fabrics {get;set;}
}
In your MVC Controller:
MyViewModel mvm = new MyViewModel();
mvm.Colors = get colors here;
mvm.Fabrics = get fabrics here;
return Json(mvm, JsonRequestBehavior.AllowGet);
In your success object in Angular:
myservice.getData()
.success(function(data){
$scope.colors = data.Colors;
$scope.fabrics = data.Fabrics;
})
Hopefully, that helps or at least gets you started.
If you ignore the fact you are using angular the answer would be to populate a view model with what you need and razor the cshtml, because you are using angular...nothing changes....because you said SERVER-SIDE that is still the answer.
If you move this to the client an angular service that can cache the data is probably the most direct way.

Insert _ViewStart.cshtml

Is that possible to use viewstart only for a particular controller and view?
I was using only _Layou.cshtml file inside views folder.
Now i added _ViewStart.cshtml as common view inside views folder and moved _Layout to Shared folder.
This is program structure:
Homecontroller
public ActionResult Index()
{
return View();
}
Index.cshtml
#{
Layout = "~/Views/_Layout.cshtml";
}
_Layout.cshtml
{
//design code for Index.chtml
}
as per the above code, _Layout rendered for homecontroller .
When done the changes mentioned at the very first line, I'm getting the controls inside _Layout.cshtml in every controller I use.
I use nearly 6 controllers.
How to make this change without disturbing the entire code.
Please help.
PS: I need to introduce _ViewStart into the program since I'm integrating openid with my already developed project.
You can create another _ViewStart.cshtml (in Views/[controller] a sub-folder for example) that will override the root one, something like:
#{ Layout = null; }
You can simply use the ViewBag to determine whether to use Layout or not:
public ActionResult AnotherAction()
{
....
ViewBag.NoLayout = true;
return View();
}
and in your _ViewStart:
#{
if (ViewBag.NoLayout == null || !ViewBag.NoLayout)
Layout = "~/Views/_Layout.cshtml";
}
You can read more about MVC3 Razor layouts on Scott Guthrie's Blog

How to add a script in a partial view in MVC4?

This is the code which I have in my partial view
#model Contoso.MvcApplication.Models.Exercises.AbsoluteArithmetic
#using(Html.BeginForm())
{
<div>
<span style="width: 110px; float:left; text-align:center; font-size:2.5em;">#Model.Number1</span>
<span style="width: 110px; float:left; text-align:center; font-size:2.5em;">+</span>
<span style="width: 110px; float:left; text-align:center; font-size:2.5em;">#Model.Number2</span>
<span style="width: 110px; float:left; text-align:center; font-size:2.5em;">=</span>
<span>
#Html.EditorFor(model => model.Result)
#Html.ValidationMessageFor(model => model.Result)
</span>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
Please note at the bottom of my code, I've got a #section, and I realized that it's not running if I set a breakpoint there. If I move that line in the _Layout.cshtml it works well, but that's not the idea.
How can I tell to MVC4 in a partial razor view that I want to add that library?
You can use
#Scripts.Render("~/Scripts/my-script.js") for .js files and #Styles.Render("~/Content/my-Stylesheet.css") for css files.
Nb: it works for a particular bundle also More details - 'http://www.asp.net/mvc/overview/performance/bundling-and-minification'
it works on any sub-pages in razor including partial views.
for more info google for the usage of these helpers
You can add the script directly at the end of the partial view html, without script section (because script section is not rendered in partial views)
<script language="javascript">
// Your scripts here
// ....
</script>
You can't render layout sections from a partial. Move the section definition to the parent page or layout.
Check out my answer How to render a Section in a Partial View, which allows you to define Scripts and Styles in any view/partial view. It also takes care of duplicate includes.
My personal take is that sections aren't a good solution for styles and javascript includes.
There is no common solution for this issue but you can do the following simplest ways:
1) You can create a set of extension method as the following:
https://stackoverflow.com/a/6671766/5208058
2) Simply move your javascript codes into a separated partial view and on your main view, render 2 partial views. One for the main partial view and the other for your scripts as the following:
{
// markup and razor code for Main View here
#Html.Partial("Main_PartialView")
}
#section Scripts
{
#Html.Partial("JavaScript_PartialView")
}
Hope it helps.
This worked for me allowing me to colocate JavaScript and HTML for partial view in same file for ease of readability
In View which uses Partial View called "_MyPartialView.cshtml"
<div>
#Html.Partial("_MyPartialView",< model for partial view>,
new ViewDataDictionary { { "Region", "HTMLSection" } } })
</div>
#section scripts{
#Html.Partial("_MyPartialView",<model for partial view>,
new ViewDataDictionary { { "Region", "ScriptSection" } })
}
In Partial View file
#model SomeType
#{
var region = ViewData["Region"] as string;
}
#if (region == "HTMLSection")
{
}
#if (region == "ScriptSection")
{
<script type="text/javascript">
</script">
}
This Stackoverflow page provided a full solution to this question: Using sections in Editor/Display templates
TL;DR: Just add the Forloop.HtmlHelpers nuget package https://www.nuget.org/packages/Forloop.HtmlHelpers/ to your project to allow you to run Javascript from Razor Partial Views and Templates in ASP.NET MVC. I have personally used this with my MVC 5 project.
If you want to include specific scripts only in some partial views and avoid spreading them unnecessarily throughout your application, you can do something like this:
Define a bundle pointing to an empty javascript file in your BundleConfig.cs:
bundles.Add(new ScriptBundle("~/bundles/empty").Include(
"~/Scripts/empty.js"
));
In the head section of your _Layout.cshtml, add this variable:
#{
ViewBag.AdditionalBundle = String.IsNullOrEmpty(ViewBag.AdditionalBundle) ? "~/bundles/empty" : ViewBag.AdditionalBundle;
}
In the bottom of your _Layout.cshtml, render any additional bundles you want:
#Scripts.Render("~/bundles/lib")
#Scripts.Render(#ViewBag.AdditionalBundle);
#RenderSection("scripts", required: false)
And finally, in the partial view in which you need any specific scripts, just add the corresponding bundle to the variable:
ViewBag.AdditionalBundle = "~/bundles/mySpecificBundle";
Partial views are rendered before the _Layout.cshtml, so you need that verification at the top of the file. It goes like this: if any partial view assigned a value to ViewBag.AdditionalBundle, then use it. Otherwise, render an empty script.
Noob trick: Define a function in an already loaded file, and call the function on partial view load.
1.Have a separate js file that you load with your usual bundle:
BundleConfig.cs
bundles.Add(new ScriptBundle("~/bundles/CustomScripts").Include(
"~/Scripts/Custom/partial-view.js"
));
Load the custom script bundle like any other bundle in your layout
_Layout.cshtml
#Scripts.Render("~/bundles/CustomScripts");
define a function, in our case OnPartialViewLoad function in the custom js file:
partial-view.js
function OnPartialViewLoad() {
// ... your onLoad work
}
add a document.ready() function to the end of your partial view and call the onLoaded function.
partialView.cshtml
<script type="text/javascript">
$(document).ready(function(){
OnPartialViewLoad();
});
</script>

ASP.NET MVC 3 Partial View in layout page

I'm working on setting up a shared content (navigation) for an asp.net MVC layout page.
Here is my partial view "_LayoutPartial.cshtml" with code to pull navigation data from a model.
#model MyApp.Models.ViewModel.LayoutViewModel
<p>
#foreach (var item in Model.navHeader)
{
//Test dump of navigation data
#Html.Encode(item.Name);
#Html.Encode(item.URL);
}
</p>
Here is how the code for my controller "LayoutController.cs" looks like.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using MyApp.Models.ViewModel;
namespace MyApp.Controllers
{
public class LayoutController : Controller
{
//
// GET: /Layout/
LayoutViewModel layout = new LayoutViewModel();
public ActionResult Index()
{
return View(layout);
}
}
}
Here is the code for the "_Layout.cshtml" page. I'm attempting to call the partial view here using Html.RenderAction(Action,Controller) method.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<p>
#{Html.RenderAction("Index","Layout");}
</p>
#RenderBody()
</body>
</html>
When the layout page executes the #{Html.RenderAction("Index","Layout");} line, it throws out an error message "Error executing child request for handler 'System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper'."
What am I missing friends? How can I call a partial view in a layout page?
Thank you all in advance!
Instead of:
public ActionResult Index()
{
return View(layout);
}
do:
public ActionResult Index()
{
return PartialView(layout);
}
If you don't do that when you return a normal view from your child action, this normal view attempts to include the Layout, which in turn attempts to render the child action, which in turn returns a view, which in turn includes the Layout, which in turn attempts to render the child action, ... and we end up with names like the one ported by this very same site.
Also in your partial you don't need to do double encoding. The # Razor function already does HTML encode:
#model MyApp.Models.ViewModel.LayoutViewModel
<p>
#foreach (var item in Model.navHeader)
{
#item.Name
#item.URL
}
</p>
First verify that your child view is inside the Shared directory
#Html.Partial("_LayoutPartial")
OR
#{Html.RenderAction("actionname", "controller name");}
And don't use #Html.Encode(), Razor is already doing for u. Just use
#item.Name
#item.URL
I have solved this error getting on Layout page
System.Web.Mvc.HttpHandlerUtil+ServerExecuteHttpHandlerAsyncWrapper
Important !
First create partial view inside shared folder
In Controller ,
public PartialViewResult Userdetails()
{
....
return PartialView("PartialViewName", obj);
}
In Layout Page,
#{Html.RenderAction("action","controller");}
I know this is an old question but I thought I would throw this in here. You can use either Html.Action or Html.RenderAction. They both technically do the same thing but depending on how much content you're returning back can have an impact on which one you should really use for best efficiency.
Both of the methods allow you to call into an action method from a view and output the results of the action in place within the view. The difference between the two is that Html.RenderAction will render the result directly to the Response (which is more efficient if the action returns a large amount of HTML) whereas Html.Action returns a string with the result.
Source

How can I run code from my layout file?

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

Resources