MVC3 is it possible to serve a view section from a controller action? - asp.net-mvc-3

Suppose I have index.cshtml
#{
ViewBag.Title = "Index";
}
#model SomeModel
#section JS{
content1
content2
content3
}
<div> View Content </div>
Is there any way I could have a controller action that would serve ONLY the section JS for a request for index.js?
Such that navigating to http://somesite/index.js would return
content1
content2
content3
Edit: Some further thoughts on this. My goal would be along the lines say creating a layout page that requires a JS section programmatically, and then composing the View to that layout page and then returning the results of this.
Psuedo code example:
var layout = new LayoutPage();
layout.DefineSection("JS", required: true);
layout.Compose(View("index"))
return layout;
I'm not set on achieving that with what I described but I feel that might offer some more insight on what I'd like to achieve.

You can do something like this (but you'd have to write your own controller action to do it properly)
Index.cshml
#model MvcApplication1.Models.TestModel
#{
ViewBag.Title = "Home Page";
}
<h2>#ViewBag.Message</h2>
<p>
To learn more about ASP.NET MVC visit http://asp.net/mvc.
</p>
#section JS {
blahblahblah
}
JSLayout:
#RenderSection("JS")
Your controller Action
public ActionResult Index() {
return View("Index", "_JSLayout", yourModel);
}
This will output only the JS section. If you want to do it programatically then it will take a bit.

The only way to do it would be to make the content of that section into a partial view, and return the partial view from the controller action.

Related

How to get model from Partial View in MVC

I have a main Index view from which I call view called Create, into which I pass type of the widget I want to create as a string.
Index view:
<i class="fa fa-image"></i> Create Image Widget -
<i class="fa fa-file-text"></i> Create Text Widget
Create Action:
public ActionResult Create(string wType)
{
ViewBag.wType = wType;
return View();
}
the type is then passed into view via ViewBag.wType and this is evaluated in the Create View
Create view:
#using (Html.BeginForm())
{
<section class="row">
#{
if (ViewBag.wType == "image")
{
Html.RenderPartial("~/Views/WidgetEditor/_CreateImageWidget.cshtml");
}
else if (ViewBag.wType == "text")
{
Html.RenderPartial("~/Views/WidgetEditor/_CreateTextWidget.cshtml");
}
}
</section>
}
and depending on this, appropriate partial view is loaded.
Partial views have different models so when the form is submitted, I do not know how which model is passed back. The one from _CreateImageWidget or _CreateTextWidget.
If the HttpPost controller look like this
[HttpPost]
public ActionResult Create(DisplayWidgetImageViewModel imageModel, DisplayWidgetTextViewModel textModel)
{
return new ViewResult();
}
I will get populated imageModel if _CreateImageWidget partial is chosen and textMode if _CreateTextWidget partial is chosen.
This is acceptable it the number of widgets types does not change, but this is not the case.
Is there a way to get somehow specific model from a partial view and know/find out which one it is or am I doing this completely wrong way?
You can create multiple forms in single page. You can also use different action methods per partial:
#using (Html.BeginForm("Action", "Controller")) {
Html.RenderPartial("~/Views/WidgetEditor/_CreateImageWidget.cshtml")
}
You all this without having to use Ajax.
I have used this answer to solve my problem: determine-the-model-of-a-partial-view-from-the-controller-within-mvc
there are also several other link with more resources.

mvc4 Razor Ajax Call to show partial view

Am trying to get a partial view to render with an AJAX call. The following ActionResult is in my base controller which is inherited by all other controllers in the solution:
public ActionResult FileManager()
{
return View("_FileManagerPartial");
}
and the folowing code is another partial that sits on the page
#Ajax.ActionLink("File Manager", "FileManager", new AjaxOptions { UpdateTargetId = "dvFilemanagerContainer" });
dvFilemanagerContainer is a div in the layout view and the partial view "_FileManagerPartial.cshtml" is in the shared views folder.
When I click the link for the ajax call, instead of loading the intended partial view it loads a duplicate of the page into the div.
Any ideas?
Edit
PartialView contents its currently just the following
<div id="dvFilemanagerWrapper">
File Manager
</div>
change your controller to
public PartialViewResult FileManager()
{
return PartialView("_FileManagerPartial");
}
In View add this line, so that with partial view, the master layout is not rendered, only partial view is rendered:
#{
Layout = null;
}
<div id="dvFilemanagerWrapper">
File Manager
</div>
Problem was to do with how my RouteConfig was handling the call. Have created a new MapRoute to point it to the right place and is now working. Thanks for help guys.

How to access the parent of a parent of a partial view's viewmodel?

In asp.net mvc3, if I have a top view:
#model BuilderVM
#using (Ajax.BeginForm("TaskSelector", ajaxOpts))
{
}
<div id="here"></div>
which gets updated with a partial view in the div id="here" returned from the action TaskSelector after a post from the Ajax form (i.e. public action TaskSelector(BuilderVM m){var vm = new SelectorVM();vm.property=m.property;return PartialView(vm);}. Inside that div, this next partial view is genereated:
#model SelectorVM
#using (Ajax.BeginForm("Choices", ajaxOpts))
{
}
<div id="selected"></div>
From that partial view, the next partial view is then updated inside the div id="selected".
#model ChooserVM
#using (Ajax.BeginForm("Ender", ajaxOpts))
{
}
<div id="ended"></div>
How, from the action "Ender"
public ActionResult Ender (ChooserVM vm)
{
//access BuilderVM.SomeProperty
}
can I access BuilderVM?
Short answer: you don't. There is no access unless the data is stored in the session.

How to TryUpdateModel from outside of Controller in MVC3

My app has modules that can be turned on and off and these modules are contributing to a view via Html.Partial calls. When the page posts back to the controller I want to have the modules take care of their individual models using something like TryUpdateModel that the controller has. Problem is that TryUpdateModel is a protected method and not accessible from outside the controller.
How can I do something like Controller.TryUpdateModel from a class outside of the controller?
If I am reading this right, it sounds like you are wanting a partial view to update itself.
I have done something similar with some jQuery, by calling an action and returning a partial view inside of a partial view. Inception?
Simple Example. - really simple
_partialViewStart.cshtml
<div id="partialFillerResult">
</div>
<script type="text/javascript">
$(document).ready(function() {
loadPartialViewFiller();
});
function loadLatestTribes() {
$("#partialFillerResult").load("#Url.Action("PartialViewFiller", "Home")").fadeIn("slow");
setTimeout(loadPartialViewFiller, 5000);
}
</script>
HomeController.cs
public ActionResult PartialViewFiller()
{
var yourModel = new ExpandoObject();
if (yourModel == null) return PartialView("_empty");
return PartialView("_partialViewFiller", yourModel);
}
_partialViewFiller.cshtml
#model dynamic
<div class="objectWrapper">
<p>
#Model.Name
</p>
</div>

Modifying MVC 3 ViewBag in a partial view does not persist to the _Layout.cshtml

I am using MVC 3 with the Razor view engine. I want to set some values in the ViewBag inside a Partial View and want retrieve those values in my _Layout.cshtml. For example, when you setup a default ASP.NET MVC 3 project you get a _Layout.cshtml file in the "/Views/Shared" folder. In that _Layout.cshtml the Page Title is set like this:
<title>#ViewBag.PageTitle</title>
Then in "/Views/Home/About.cshtml" view the contents of the ViewBag are modified:
#{
ViewBag.Title = "About Us";
}
This works fine. When the About view is rendered the page title is "About Us". So, now I want to render a Partial view inside my About view and I want to modify the ViewBag.Title inside my Partial view. ("/Views/Shared/SomePartial.cshtml")
#Html.Partial("SomePartial")
In this Partial view I have this code:
#{
ViewBag.Title = "About Us From The Partial View";
}
When I debug this code I see the ViewBag.Title get set to "About Us" and then in the Partial view I see it get reset to "About Us From The Partial View", but when the code hits the _Layout.cshtml it goes back to "About Us".
Does this mean that if the contents of the ViewBag are modified in a Partial view, those changes will not appear(be accessible) in the main view (About.cshtml) or the _Layout.cshtml?
Thanks in advance!
If you pass the ViewBag into the partial's viewdatadictionary, then pull it out (and cast), you can do whatever you want and the reference is kept. The cool part is that since it's dynamic, you can even add properties and then they'll show up on the parent page's Viewbag.
Page:
//set the viewbag into the partial's view data
#{Html.RenderPartial("Elaborate", Model, new ViewDataDictionary { {"vb", ViewBag}});}
Partial:
#{
var vb = ((dynamic)ViewData["vb"]);
vb.TheTitle = "New values";
}
Page
#ViewBag.TheTitle = "New value"
I also had this problem, and couldn't find any neat and obvious solution.
The solution I came up with was to implement an Html extension method that returns a 'PageData' class that you define, containing whatever data you need:
[ThreadStatic]
private static ControllerBase pageDataController;
[ThreadStatic]
private static PageData pageData;
public static PageData GetPageData(this HtmlHelper html) {
ControllerBase controller = html.ViewContext.Controller;
while (controller.ControllerContext.IsChildAction) {
controller = controller.ControllerContext.ParentActionViewContext.Controller;
}
if (pageDataController == controller) {
return pageData;
} else {
pageDataController = controller;
pageData = new PageData();
return pageData;
}
}
It finds the top-level controller for the current request, and returns the same PageData object every time the method is called within the same HTTP request. It creates a new PageData object the first time it is called in a new HTTP request.
The partial view gets its own ViewBag.
You can get the page's ViewBag from ((WebViewPage) WebPageContext.Current.Page).ViewBag
You can do this trick in your partial view to override the title in your _Layout.cshtml:
#{
ViewBag.Title = "About Us From The Partial View";
}
......
<script type="text/javascript">
document.title = "#ViewBag.Title";
</script>
As others have pointed out Layout, Views and Partials get their own ViewBag. However, I was able to get it to work with the following:
In the View or Partial.
#{ Html.ViewContext.ViewBag.Title = "Reusable Global Variable"; }
Then in _Layout
#Html.ViewContext.ViewBag.Title
By explicitly using the ViewContext, the views 're-use' the same ViewBag.
If anyone is still looking for a solution to this it appears that you can do it with TempData:
TempData["x"] = x;
TempData is persisted until it is read so you can just read it in your _Layout. You just have to be careful that you read everything so that it is cleared for the next request.
I've tried the following and it works:
In the (parent) view...
#Html.Partial("SomePartial", ViewData, null)
Note: ViewData is passed as the model argument, but you have to specify null for the viewData argument to use the correct overload. You can't use ViewBag because Html.Partial doesn't like dynamics.
Then , in the partial view...
#model ViewDataDictionary
#{
Model["Title"] = "About us from the partial view";
}
Of course, if you need to use the model argument for a real model, you'll have to be more creative.
try #SLaks code with
(((WebViewPage) WebPageContext.Current.Page).ViewBag).PropertyName
I encountered the same problem when I use mvc3, and I found that
this.ViewBag.ViewBag.PropertyName
works in your custom control.
I this is what page data is designed for. Pop this into your view.
#Page.somePropertyName = "Whatever you want";
And then access it in your layout view. Be sure to check that its not null first.
#{
if(Page.somePropertyName != null)
{
//Do stuff
}
}

Resources