Rendering part of a view from another view - asp.net-mvc-3

I'm moving my WebForms project to MVC and having a hard time designing things.
The basic display of my app is in _Layout. The page is divided into 4 parts(say Part A,B,C and D), with 3(A,B,C) just containing html and one(D) is dynamic. I had used #RenderBody to bring in the content of Part D. However, now the other parts are changing and I need separate controllers for these parts. What is the best way to get their contents to be displayed into _Layout?
#Html.RenderPartial / #Html.Partial / #Html.RenderAction / #Html.Action ?
I'm currently trying to replace Part C by using -
#Html.Action("Index", "CController")
However, this is not working.
In Index.cshtml for CController, I've the Layout = null, initially it was set to point to _Layout.cshtml, but I read here that this created issues.
After putting the C Part in CControllers view, it does not event display the basic _Layout page that it displayed earlier.
Here's the Index.cshtml of CController -
<div id="noteContainerDiv">
Here goes all the data to display
</div>
And Here's the code for CController.cs -
public class CController : Controller
{
public ActionResult Index()
{
return PartialView();
}
}
Can anyone suggest the right way to design this?

What you could do is have a view model for your subview (the one you call D) and pass in this view model from your layout view.
I.e. by doing something like this in your _Layout:
#Html.Partial("_SubviewD", Model.SubviewDModel)
Then obviously in your controllers you need to initialize this subview model and include it in your model (or alternatively, in the ViewBag--apologies for suggested being evil!) You could even find ways to do this without changing all your controllers (for example through a base Controller class and overriding OnActionExecuted).

There are many ways you could do this. But I would stick to your initial approach.
Have your CController Index action return a PartialViewResult instead of a full result.
You don't set the layout for partial views. So in your CController index action you'll have something like this:
var model = ....
return this.PartialView("NameOfYourPartialView", yourModel);
And when you call
#Html.Action("Index", "CController")
Everything should be OK, cool?

Related

Asp MVC AjaxExtensions, call from controller

I'm sure this is simple but I'm struggling to find it
Inside a controller you can do something like this:
public ActionResult MyAction()
{
string url = Url.Action(action, controller),
// do something with the url
}
What's the Ajax equivalent? i.e. where you would call Ajax.ActionLink in a View whats the equivalent for the controller?
Elaboration-
I have a master/detail arrangement with a grid and some input elements. You can click on select/delete in the grid to amend or delete the line.
The grid is a Kendo UI grid, the view is rendered via:
a partial view to render the input elements
creating a json object, i.e.
#{
var jsLines = #Html.Raw(Json.Encode(Model.Lines));
}
Binding the Kendo grid to this json
From within the grid I want to hit on select and call an Ajax method to update the partial view with the form details
thanks
You can use Url.Action from the razor view. Something like :
$.ajax({
url: '#Url.Action("Action", "Controller")',
...
I'm not at all convinced that this is the right way to go but it's always good to have options.
Ajax.ActionLink seems to be the same as Url.Action but with a few attributes thrown in. So you can use this:
return string.Format("<a data-ajax='true' data-ajax-mode='replace'
data-ajax-update='{2}' href=\"{0}\">{1}</a>",
Url.Action(action, controller, routeValues),
text,
"formContainerSelectSection");
to update this:
<div id="formContainerSelectSection">
... stuff to be replaced via ajax
</div>
I accept, especially after the discussion with NicoD, that there are other and probably easier ways to do this, in particular this is creating a link in the controller, that's the Views job, but the original question was about how to do this

Calling aspx page in mvc3 gives error- the view must derive from ViewPage, ViewPage<TModel>, ViewUserControl, or ViewUserControl<TModel>

I am calling an aspx page in mvc3.
It gives an error
The view at '~/WebForms/Calendar/Schedule.aspx' must derive from
ViewPage, ViewPage, ViewUserControl, or
ViewUserControl.
I have added the following code in the global.asax.cs
routes.MapPageRoute(
"Schedule",
"Classes/ManageSchedule",
"~/WebForms/Calendar/schedule.aspx"
);
and following code in the Classes controller
public ActionResult ManageSchedule()
{
return View("~/WebForms/Calendar/Schedule.aspx");
}
Your aspx pages will not be served out by a controller action. You should remove the ManageSchedule action from your controller.
In order to route your url /Classes/ManageSchedule to /WebForms/Calendar/schedule.aspx just take your MapPageRoutes that you have, and move it above the routes.MapRoute() that MVC uses to register the controller routes. The way the routes work is - the first match wins.

zend framework display/process form using same action/view?

Using MVC architecture (Zend Framework), should you use a single view with if statements to display/process a form, or multiple views (i.e. one view to display form, one to display result).
In this instance, I am trying to produce a google like search engine. The layout of the page will fundamentally change when displaying search results.
For example; Controller:
public function indexAction()
{
if (!$this->getRequest()->isPost()) {
// display form
} else {
if ($this->_request->isPost()) {
if (!$form->isValid($formData)) {
// re-display form with errors
} else {
// process form and;
// display result using same action/view?
// display result using same action but use a different view?
}
}
}
}
Using the same view:
<?php if(isset($this->form)) : ?>
<!-- show form -->
<?php else: ?>
<!-- show result -->
<?php endif; ?>
Hope that makes sense.
Don't get caught up in the old monolithic style of coding where one hunk of code does everything for one output page. The whole point of MVC is so separate responsibility. Think of a view as a template for a single piece of output, regardless of what page/url it appears on. The form is one piece of output. The search results is another. Use two views.
Less if-s -- less bugs. I propose you to use more different views here, that can reuse one form.

How would I structure this in Zend Framework?

I'm coming from CodeIgniter, and the terminology overlap between it and other MVC frameworks (particularly Zend) is giving me a mental block of some kind.
I want my users to visit http://mysite.com/do/this.
I understand that "do" is the Controller, and "this" is a function (well, method) within that Controller.
My site will have common elements like a header and sidebar; I understand that those go into a Layout, which will be incorporated into the final output.
I want the /do/this page to display three visual blocks of information (I'm deliberately not using the word "modules"). Let's call them BlockA, BlockB, and BlockC. Maybe one is a list of "new events" and another is a list of "new posts" and another is something else. Whatever. The trick is, these blocks of information will also be displayed on other pages of the site - say, http://mysite.com/did/that.
Both the "did" and the "do" Controllers (and the "this" and "that" methods, obviously) would be arranging BlockA, BlockB, and BlockC differently. Each Controller would have different criteria for what went into those blocks, too - one might be current information, while another might be archived information from the past.
I want to ensure that future programmers can easily alter the appearance of BlockA, BlockB, and/or BlockC without having to touch the code that populates their data, or the code which arranges them on each page.
So my general feeling is that BlockA, BlockB, and BlockC need to have their visual layout defined in a View - but that View wouldn't be specifically associated with either the "do" or the "did" Controllers. And the code which populates those blocks - that is, queries information from a database, selects the bits that are to be displayed, and whatnot - shouldn't reside entirely in those Controllers, either.
I started down the path of putting the logic - that is, assembling what will be displayed in each block - into Models. I feel I'm on the right path, there; both the "do" and "did" Controllers can thus summon the block-creation code via Models. But how (and where) do I abstract the visual element of those blocks, in such a way that the visual elements can also be shared by these two Controllers? Do the Models somehow load a View and output HTML to the Controllers (that doesn't feel right)? Or is there a way for the Controllers to run the Model, get the data to display, and then somehow feed it to a common/centralized View?
I know how I'd do this in CodeIgniter. But... what's the correct architecture for this, using Zend Framework? I'm convinced that it's very different than what CodeIgniter would do, and I want to start writing this application with the right architecture in mind.
One small naming thing: /:controller/:action/* => /do/this = this is an action (although also both a function and a method in the controller, action is the proper name)
Your blocks to me sound like "partial views". There are a few ways to approach this problem, and depending on how the views work, or what information they need to know, you adapt your strategy
Rendering Partials
You want to use this method when you have some view code you want to be used by multiple views. There are two different approaches using the view helpers Zend_View_Helper::render or Zend_View_Helper_Partial* The render($phtmlfile) view helper is more efficient, the partial($phtmlfile, $module, $params) view helper clones a new view, unseting all parameters, and setting the ones you pass in. An example of how to use them:
case/list.phtml:
<?php
$this->headTitle($this->title);
// works because our controller set our "cases" property in the view, render
// keeps our variables
echo $this->render("case/_caseListTable.phtml");
case/view.phtml
<?php
$this->headTitle($case->title);
?><!--- some view code showing the case -->
<?php if ($cases = $case->getChildren()): ?>
<h3>Children</h3>
<?php echo $this->partial("case/_caseListTable.phtml", "default", array(
"cases"=>$cases,
)); ?>
<?php endif; ?>
case/_caseListTable.phtml
// table header stuff
<?php foreach ($this->cases as $case): ?>
// table rows
<?php endforeach; ?>
// table footer stuff
Custom View Helpers
Sometimes the controller has no business knowing what information is being displayed in the block, and preparing it for your view would be silly, at this point you want to make your own view helpers. You can easily add them to the global view in application.ini:
resources.view.doctype = "XHTML1_STRICT"
resources.view.helperPath.My_View_Helper = APPLICATION_PATH "/../library/My/View/Helper"
I have a tendency to use this method for things that will require additional information from the model not provided by the controller, or blocks of reusable formatting code for the view. A quick example, from a project that I used: Olympic_View_Helper_Ontap grabs the draught beer list and renders it:
class Olympic_View_Helper_Ontap extends Zend_View_Helper_Abstract {
public function Ontap()
{
$view = $this->view;
$box = Olympic_Db::getInstance()->getTable('box')->getBoxFromName('Draught-Beer');
if ($box) $menu = $box->getMenu(); else $menu = null;
$content = "";
if ($menu)
{
$content = "<h1>".$view->escape($menu->title)."</h1>";
$content .= "<ul>";
foreach($menu->getItems() as $item) {
$content .= "<li>".$view->escape($item->name)."</li>";
}
$content .= "</ul>";
}
return $content;
}
}
Then in my layout:
<?php echo $this->ontap(); ?>
Your View Helpers can also accept arguments (of course), can call other view helpers (including partial). Consider them template functions. I like using them for short tasks that are required a lot, for instance $this->caseLink($case) generates a properly formatted <a href='/case/2' class='case project'>Project</a> tag.

How do you build a Single Page Interface in ASP.NET MVC?

I want to build a webapplication with a "Single Page Interface", using ASP.NET MVC.
I have searched if this was at least possible and I think the answer is: not by simple means (reading http://msdn.microsoft.com/en-us/magazine/cc507641.aspx#S2 second-last paragraph; that article is from May 2008, though).
I found other examples which implemented this by coding/hacking with jQuery. However, I'm looking for a clean solution, using standard .NET approaches, if possible.
What I want is precisely the same functionality when you create a new "MVC Web Application". However, instead of links to "/Home/About" which reloads the entire page, I want links to "#Home/About" which loads only the new part via AJAX.
The standard approach of calling templates (partial views) with Html.RenderPartial is exactly what I want, only then loading them in through AJAX-requests.
Of course, it might be that I can't use these templates that are rendered by the Master-page for some reason (maybe it's expecting to always be called in a certain context from a certain place or so). But maybe there's another clean solution for how to build your template-pages and fetching them from the Master-page.
Who has a nice solution for implementing such thing, a Single Page Interface?
PS: I'm developing in Visual Web Developer 2008 Express Edition with MVC 1.0 installed, in C#
[edit]
Below I read that working with the templates is possible and that jQuery looks indeed like inevitable, so I tested it.
The following code transforms regular links created by Html.ActionLink into anchor-links (with #) to contain history, and then fetch the page via AJAX and only injecting the html-part I'm interested in (i.e. the partial page inside div#partialView):
$("a").each(function() {
$(this).click(function() {
$("div#partialView").load($(this).attr("href") + " div#partialView");
location.hash = $(this).attr("href");
return false;
});
});
These links also allow for graceful degredation.
But what I have left now, is still fetching the whole page instead of only the partial page. Altering the controller didn't help; it still provided me html of the whole page, with all of these statements:
public ActionResult About()
{
return View();
return View("About");
return PartialView();
return PartialView("About");
}
How could I only return the content of the part I'm interested in (i.e. the contents of Home/About.aspx)?
What I'd like is POSTing a value with AJAX (e.g. "requesttype=ajax") so that my controller knows the page is fetched via AJAX and only returns the partial page; otherwise it will return the whole page (i.e. when you visit /Home/About instead of #Home/About).
Is a good practice to alter Global.asax.cs maybe, to create a new routing schema for AJAX-calls, which will only return partial pages? (I haven't looked into this much, yet.)
[edit2]
Robert Koritnik was right: I also needed an About.ascx page (UserControl) with only the small HTML-content of that page. The first line of About.aspx was linked with the Master-page via MasterPageFile="~/..../Site.master" which caused that all HTML was printed.
But to be able to execute the following in my controller:
public ActionResult About()
{
return Request.IsAjaxRequest() ? (ActionResult)PartialView() : View();
}
I needed to alter the way a PartialView (.ascx file) and a View (.aspx) file was found, otherwise both methods would return the same page (About.aspx, ultimately resulting in an infinite loop).
After putting the following in Global.asax.cs, the correct pages will be returned with PartialView() and View():
protected void Application_Start()
{
foreach (WebFormViewEngine engine in ViewEngines.Engines.Where(c => c is WebFormViewEngine))
{
/* Normal search order:
new string[] { "~/Views/{1}/{0}.aspx",
"~/Views/{1}/{0}.ascx",
"~/Views/Shared/{0}.aspx"
"~/Views/Shared/{0}.ascx"
};
*/
// PartialViews match with .ascx files
engine.PartialViewLocationFormats = new string[] { "~/Views/{1}/{0}.ascx", "~/Views/Shared/{0}.ascx" };
// Views match with .aspx files
engine.ViewLocationFormats = new string[] { "~/Views/{1}/{0}.aspx", "~/Views/Shared/{0}.aspx" };
}
RegisterRoutes(RouteTable.Routes);
}
Full view vs. Partial view
Seems like you've messed up something. If you create an About.aspx page with all the HTML needed to display the whole page it doesn't really matter if you say
return PartialView('About');
The view still returns all the HTML that's written in it.
You should create a separate About.ascx that will only have the content of the page itself without the header and other stuff that's part of the whole page.
Your original page About.aspx will have something like this in its content (to avoid repeating writing the same content twice):
<%= Html.RenderPartial("About") %>
And you can have two controller actions. One that returns a regular view and one that returns a partial view:
return View("About"); // returns About.aspx that holds the content of the About.ascx as well
return PartialView("About"); // only returns the partial About.ascx
Regarding routes in Global.asax
Instead of writing separate routes for Ajax calls you'd rather write an action filter that will work similar as AcceptVerbsAttribute action filter. This way your requests from the client would stay the same (and thus preventing the user from manually requesting wrong stuff), but depending on the request type the correct controller action will get executed.
Well, you can load Partial View through AJAX request. In example, I'll use jquery to make an ajax call.
These could be the action in controller (named HomeController):
public ActionResult About()
{
//Do some logic...
//AboutView is the name of your partial view
return View("AboutView");
}
JQuery ajax call to place the retured html in place you want:
var resultDiv = $('#contentDIV');
$.ajax({
type: "POST",
url: "/Home/About",
success: function(responseHTML) {
resultDiv.replaceWith(responseHTML);
}
});
[edit-question is updated]
It is possible to do exactly what you want. First controller action can give you back the partial view, so mine "AboutView" could have been something like this:
<table>
<tr>
<th>
Column1Header
</th>
<th>
Column2Header
</th>
</tr>
<tr>
<td>
...
</td>
<td>
...
</td>
</tr>
and this HTML is exactly what are you going to have in responseHTML on success handler in jquery ajax method.
Second, you can distinguish in controller action if the request is an ajax request:
public ActionResult About()
{
//partial AboutView is returned if request is ajax
if (Request.IsAjaxRequest())
return View("AboutView");
else //else it will be the default view (page) for this action: "About"
return View();
}
We've got a site that does exactly this, and you really want to use the jQuery route here--alot easier to implement in the long run. And you can easily make it gracefully degrade for users who don't have javascript enabled--like google.
it isn't all that clear what are you asking for, is it for a complete example or for some specific functionality? You should be able to do this without JQuery for simple scenarios, you can use the Ajax view helpers like the ActionLink method. Also, I don't really understand what is your issue with RenderPartial, but maybe you're looking for something like RenderAction from ASP.NET MVC Futures.
ASP.NET MVC 4 (now in beta) adds support for Single Page Applications in MVC.
http://www.asp.net/single-page-application
UPDATE:
...and they removed it from the MVC 4 RC
UPDATE:
...and it is back with the 2012 Fall update

Resources