dynamically changing #section in asp.net view - asp.net-mvc

I am working on asp.net MVC 3 application and I have a layout page with a section like this:
<div class="rt-block">
<div id="rt-mainbody">
#if (IsSectionDefined("BodyTitle"))
{
<div class="rt-headline">
<h1 class="rt-article-title">
#RenderSection("BodyTitle", false)
</h1>
</div>
}
<div class="clear">
</div>
<div>
#RenderBody()
</div>
</div>
</div>
In My View, I am defining the section like this:
#section BodyTitle {
<span>Verify</span> Your Identity
}
partail view here
This View loads one of two partial views depending on link click.
I want that when one partial view is loaded then section has different text where it should have different text when other partial view is loaded. How can I change section contents on change of partial view ?
I tried to move section to partial views but in that case it is not loaded at all. Can't we define section in partial view which is declared in layout view ?
Please suggest

You cannot define sections in partial views. They must be defined in the main view. So basically what you need is to update 2 different portions of your DOM when a link is clicked. One possible way to achieve this is to render the partial view to a string inside the controller action and then return a JSON result containing the 2 properties with the corresponding partial contents.
return Json(new
{
partialHtml = RenderPartialViewToString("_SomePartial"),
sectionHtml = RenderPartialViewToString("_SomeSection")
});
and then:
$.ajax({
url: '...',
type: 'POST',
success: function(result) {
// first update the partial
$('#partialContainerId').html(partialHtml);
// now update the section
$('.rt-article-title').html(sectionHtml);
}
});
You could externalize the contents of the section inside a partial.

Related

Partial Views, redirected to another URL?

Am trying to build a project using MVC 4 and Razor. Am having trouble understand partial views. I have a list of my domain objects that I iterate through and display it in a list box (each row being clickable). I split this into main view and a partial view which renders the domain object which works fine. Inside my partial view I want to make each item clickable and upon click, I want to create a new partial view displaying details about the domain object.
Here is what I have
My main view looks like this
<div class="panely">
<div class="list-group">
#{ Html.RenderPartial("DomainObjectsPartial");}
</div>
</div>
My partial view looks like this
<div class="list">
#foreach (var x in #Model)
{
<a href="#Html.Partial("DomainObjectPartial")" class="list-item">
<em>#x.Name</em>
</a>
}
</div>
I have a view named DomainObjectPartial, which has nothing but a small div with hello.
When the user clicks on a domain object, I expect the partial view to be rendered within the main view, but instead I get a error saying
A potentially dangerous Request.Path value was detected from the
client (<).
And when I look at my URL, the contents of the partial view are contained within it like
http://localhost/<div>hello</div>
I dont want to be redirected to another URL. I just want the partial view to be displayed below the list. Can anyone explain to me what am i missing or not understanding?
I guess you wanted to use AJAX:
<div class="list">
#foreach (var x in Model)
{
<a href="#Url.Action("Index", "Items", new { id = x.Id })" class="ajax-link">
<em>#x.Name</em>
</a>
}
</div>
and then you will obviously have a controller action which will render this partial:
public class ItemsController: Controller
{
public ActionResult Index(string id)
{
// go get the specific item from your database using the id and pass it to
// the partial view
var viewModel = ...
return Partialview("DomainObjectPartial", viewModel);
}
}
and the last part is to AJAXify this anchor:
$(function() {
$('.ajax-link').on('click', function() {
// Send an AJAX call to the server endpoint pointed by the href attribute
// of the anchor and inject the results of this endpoint execution inside a
// DOM element with id="result"
$('#result').load(this.href);
// By returning false you are canceling the default action of the
// anchor click and prevent the browser to redirect to the url pointed
// by the href property. This would leave enough time for your AJAX request
// to execute and return the results.
return false;
});
});
and you will obviously need a DOM element with id="result" somewhere on your page to harbor the results of the AJAX call:
<div id="result"></div>

How can I inject templates into a view in ASP.NET MVC?

UPDATE:
More general question what is the way to make a higher-order composition of views? The same way you pass a delegate into a method.
ORIGINAL QUESTION:
I have a page view and a control as a partial view. From the page view I render the control using Html.Partal("MyControl", myControlModel). Now this control has some areas that I wish were customizable from the page view. So that if the control is rendered from a different page these areas are filled with different content. Basically what I am looking for is a way to inject a piece of HTML from the page view into a partial view. Can I do it in MVC? If so, how?
Example:
Page view:
<div class="page">
#Html.Partial("MyControl", myControlModel, #<text>My <b>custom</b> piece of HTML which is different for each page<text>)
</div>
My control view:
<div class="my-control">
<div class="common-part-for-all-pages">
#Model.Value
</div>
<div class="part-that-has-to-be-customized">
#* there must be a piece of HTML provided somehow from the page view *#
</div>
</div>
Expected result:
<div class="page>
<div class="my-control">
<div class="common-part-for-all-pages">
#Model.Value
</div>
<div class="part-that-has-to-be-customized">
My <b>custom</b> piece of HTML which is different for each page
</div>
</div>
</div>
Add new properties to the viewmodel of the partial: "TemplateName" and "TemplateModel". Then do
<div class="my-control">
<div class="common-part-for-all-pages">
#Model.Value
</div>
<div class="part that has to be customized">
#Html.Partial(Model.TemplateName, Model.TemplateModel)
</div>
</div>
Or you could just add a string property "Template" and do
<div class="my-control">
<div class="common-part-for-all-pages">
#Model.Value
</div>
<div class="part that has to be customized">
#Html.Raw(Model.Template)
</div>
</div>
Call it like this
#{
// just set the property
myControlModel.Template = "some html";
myControlModel.Template = Html.TextBox(/*...*/).ToString();
myControlModel.Template = Template("hello").ToString();
}
#Html.Partial("MyControl", myControlModel)
#helper Template(string text)
{
<span>#text</span>
}
ToString() isn't necessary if MvcHtmlString type is used.
You'd need to create controller actions for this, but you can use #Html.Action("MyAction", "MyController", myModelObject) and pass any parameters from the page to partial view in the myModelObject parameter. It can be a bit of overkill but if your control/partial view needs to do any special C# code then this way works pretty well.
Make a class PartialModel, give it two properties string Name and object Model, then use #Html.Partial(pm.Name, pm.Model) in your partial view.
If you want to put different HTML inside every time, the above won't work, so read on.
You can use something similar to Html.BeginForm:
#using (Html.BeginMyContainer())
{
<h3>Hi!</h3>
<p>This is some custom content.</p>
}
(This would be a BeginMyContainer extension method on the HtmlHelper class.)
Your Html.BeginMyContainer method should return a class inheriting from MvcForm, which is IDisposable. In the BeginMyContainer method you'll write whatever HTML comes before the custom content of your container, and in the Dispose method of the returned MvcForm you'll write whatever HTML comes after your custom content.
When Razor processes the code I have above, it will:
Run the BeginMyContainer method at the start of the using statement, writing whatever HTML comes before the custom content
Write the HTML custom content inside of the using statement
Call Dispose on the MvcForm at the end of the using statement, writing whatever HTML comes before the custom content
Related: rolling my own #Html.BeginfBrm()

render partial view in MVC

I am using MVC Structure. I have to create a report which can be filtered by drop downs. I am thing to use a partial view to display report.
HEre is the structure of the page I want to achieve.
On top of page, there will be some drop down lists.
Below these will be page for report.
when user changes the options from dropdownlist, the report will be filtered.
I have two questions
1. How to render partial page.
2. How to refresh partial page through ajax/jquery. I want to do this on client side.
I have checked online, I am rendering page as shown in code below
VIEW
<h3>Report</h3>
<div>
<table>
<tr>
<td>ServiceLine</td>
<td>#Html.DropDownList("ServiceLine", null, new {id="ServiceLine"}) </td>
</tr>
</table>
</div>
<div>
<h2>List</h2>
<div>
#Html.Partial("PartialView")
</div>
</div>
This is what I have got in controller
public ActionResult PortfolioReport(char serviceLine)
{
//Department List
var serviceLines = Enum.GetValues(typeof(SogetiDepartments)).Cast<SogetiDepartments>().Select(v => new SelectListItem
{
Text = v.ToString(),
Value = ((char)v).ToString(),
});
foreach (SelectListItem item in serviceLines)
{
if (Convert.ToChar(item.Value) == serviceLine)
item.Selected = true;
}
ViewBag.ServiceLine = serviceLines;
return View();
}
Any kind of help is appreciated.
You have to use jQuery to achieve this feature
First apply some identifier to your data container
<div id="reportContent">
#Html.Partial("PartialView")
</div>
And then write script on your dropdown change event using jQuery
<script type="text/javascript">
$(function(){
$("#ServiceLine").change(function{
// get data from server using ajax
var url = 'YourPartialPageURL?'+serviceLine+="="+$(this).val();
$('#reportContent').load(url);
});
});
</script>
Note: You should use return PartialView(); from your controller action
And don't use #Html.Partial and use #Html.Action instead.
#Html.Partial loads View directly without going to Controller Action.
It should be used if you have data to be passed with you or if you just want to load some static content on the page

dont display div data not provided

I am working with mvc4 and displaying data from my model in to cshtml views.
When setting data in to the markup, I adding it in to div tags.
Is there a way in mvc that if the model property is not set, dont display the div?
Sample of my markup
<div class="myclass"> #Model.Text </div>
You can test for a value being set like so:
#if (!string.IsNullOrEmpty(Model.Text))
{
<div class="myclass"> #Model.Text </div>
}
Update: If you want to incorporate the logic for whether or not to render an element based on its value, you could create a Custom HTML Helper method.
How about wrapping it in a null check
#{
if (#Model.Text != null)
{
<div class="myclass"> #Model.Text </div>
}
}

Cookieless rendering of a side bar with links enabled based on a parameter

I have an MVC 4 site that renders a left sidebar with a bunch of menu links on it. When the user signs in, they are directed to a page where they search for someone. Once they've selected someone and submitted the form, an id cookie gets set.
This id determines whether or not various links in the sidebar menu are enabled, as it is a required parameter for many of the actions that those links lead to. The menu itself, since it is on every page of the site, is set up in the _Layout partial:
<div id="contentwrapper">
<div id="left-menu">
#Html.Action("Display", "Menu", new { Area = "" })
</div>
<div id="mainbody">
<section>
#RenderBody()
</section>
</div>
<div id="footer">
</div>
</div>
Display returns a partial view representing the sidebar menu. Since I'm rendering the menu sidebar in the _Layout, I don't have a model to work with. Is there any way I can get the parameter to my menu partial view without using a cookie?
I would use a hidden field and viewbag
Public ActionResult Index(){
ViewBag.id = // set your id initially
}
if javascript/jquery is ok with you...
$(function(){
var myID = #Html.Raw(Json.Encode(ViewBag.id));
$('#hidID').val(myID);
});
HTML
<input type="hidden" name="hidID" id="hidID" />
Then.. Display Action
Public ActionResult Display(int hidID){
// this will be current id,
// if id is reset , pass the new one to viewbag , jquery will reset hidden field on client
}

Resources