view sections cause problems if not rendered in layout - asp.net

I'm converting an MVC aspx content place holder -> master page to an MVC razor section -> layout.
In the past when my aspx view came to something like this:
<asp:Content ID="HelpContent" ContentPlaceHolderID="HelpLink" runat="server">
Help
</asp:Content>
And the master page didn't have a corresponding HelpContent place holder (perhaps because a user was not authenticated) everything rendered fine (with no HelpContent section).
Now when I have a razor section defined that does not have a corresponding #RenderSection in the layout, I get this error:
The following sections have been defined but have not been rendered
for the layout page "~/Views/Shared/New.cshtml": "HelpLink".
Do I need to redesign this?
Is there a way I can have the view's HelpLink section render optionally if the layout gives it the green light?
EDIT:
I think there's some confusion, so let me re-summarize:
The layout logic looks like this:
if (User.IsLoggedIn) {
#RenderSection( "HelpLinks", false);
}
But then the user isn't logged in, it doesn't render, and then .NET throws an exception because the layout doesn't know what to do with the section.

You can indicate that the section is optional by passing false as the second argument:
#RenderSection("HelpLink", false);
Edit: In the case of control flow logic for rendering, you can use .NET in the razor view (like this c# example):
#if(IsSectionDefined("HelpLink"))
{
#RenderSection("HelpLink", false);
}
Or, if you want to base rendering on whether the user is logged in, you could replace the if logic in the above sample with your security check.
Edit 2:
Make sure you have defined the section:
#section HelpLink {
//This needs to be defined in any view that uses the layout with the #RenderSection. It can be empty.
}
Alternatively, you can add the check to see if the section exists and only define the #section in the required view:
if (IsSectionDefined("HelpLink") && User.IsLoggedIn) {
#RenderSection( "HelpLinks", false);
}

If a section is declared in a razor view it has to be rendered in the layout.
I found this in Freeman's Pro ASP.NET MVC 5 book.
Seems like a bad design to me.

Related

How To Set Default Layout For ASP Razor MVC

I am assuming there is a way to set a default layout to use if one is not selected, but I cant seem to find any documentation on it.
From the controller, if I call return View() it returns the page without any of the html from the layout. If i return the view as follows, the layout shows up fine.
return View("Index", "~/Views/Shared/_PublicLayout.cshtml");
So I'm wondering if there is a way to set the default variable for the layout so i don't have to specify it every time for every view.
In the views folder locate or create file _ViewStart.cshtml and inside you can define:
#{
Layout = "~/Views/Shared/_Layout.cshtml";
}
where _Layout.cshtml is your default layout.

Equivalent to Razor Section Helper In Sitecore

I am trying to include different scripts on different pages in Sitecore and can't seem to find a very good way of doing this. In a normal mvc project I could add the #Section{} helper and use that on different partial views to specify where I want those scripts in the layout view, but I haven't been able to find an equivalent for the way that Razor helper is implemented with Sitecore. I'd like to do this without using a place holder, I don't want to add a view in Sitecore every time I need to add a script file.
Thanks in advance.
I'm afraid you're out of luck here.
#Section is not supported because Sitecore doesn't render the Razor views in the same way as MVC does.
A Sitecore MVC layout is basically just a regular view that is rendering several other partial views or controller actions.
So when the placeholders in the <body> of your layout view are being rendered, the <head> section of that layout has already been rendered.
There is no such thing as deferred rendering in Sitecore MVC like you can do with #Section.
Everything in the view is executed from top to bottom, so if you can put your scripts at the end of your layout (like before the </body>), you can still manipulate data in the views or actions that are executed earlier.
The way I have it setup in my current Sitecore MVC solution is my layout has an extension method call to RenderScripts() at the bottom before the closing body tag.
#Html.RenderScripts()
That extension method looks like this:
public static IHtmlString RenderScripts(this HtmlHelper htmlHelper)
{
var templates = (from object key in htmlHelper.ViewContext.HttpContext.Items.Keys
where key.ToString().StartsWith("_script_")
select htmlHelper.ViewContext.HttpContext.Items[key]).OfType<Func<object, HelperResult>>()
.Select(template => template(null)).ToList();
foreach (var template in templates)
{
htmlHelper.ViewContext.Writer.Write(template);
}
return MvcHtmlString.Empty;
}
Then on each MVC Razor View when I want to include a .js file that is specific to that rendering I call something like below at the bottom of the file:
#Html.Script(
#<script src="#Url.Content("~/js/custom/orderdetail.js?t=11172015")" type="text/javascript"></script>
)
Below is the Script extension method:
public static MvcHtmlString Script(this HtmlHelper htmlHelper, Func<object, HelperResult> template)
{
htmlHelper.ViewContext.HttpContext.Items["_script_" + Guid.NewGuid()] = template;
return MvcHtmlString.Empty;
}
This has worked out well for us and I think it is what you are trying to do.
Indeed, the Section-helper isn't supported in Sitecore. If you're using MVC4 you can maybe use Bundles to solve your problem. For more information see: http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification
You can also create multiple bundles for specific views. In a single Bundle you can add multiple script and output it in your view by adding #Scripts.Render()

How navigate to next page using AJAX in MVC4?

I don't have so much experience using AJAX in a MVC application, in fact is my first facing. Please check the below image and note the rectangles.
The image is just an example that I took from internet.
The biggest rectangle is a partial view in my application and I have to render it when the user press Continue or Continuar button. The application should replace the current view for another without refresh the page.
This is the code which I'm testing, note first that I'm passing the first element of a list, but when the user press the button, render the view with the next element index = 2.
public ActionResult DoTest()
{
if (!Request.IsAjaxRequest())
{ }
List<Worksheet> worksheets = new List<Worksheet>()
{
new Worksheet("Hoja 1", ...),
new Worksheet("Hoja 2", ...)
};
return View(worksheets[0]);
}
Can orient me a little bit to know how to implement this feature? I just know that I need to use Ajax.
Have a look through the tutorials and examples here. There's plenty of other material around on the web with information on this subject.
There are many different ways you can achieve this. One way would be to write a custom paging Helper (HtmlHelper) that accepts new content upon the post event. You can view all about Helpers here : Custom HTML Helpers
Another way could be to use partial page rendering to achieve the partial page update upon post event.
If I was you I would combine a partial view with a jquery function to update the content. You can view some help on that here: Change dive content with Jquery

Disable javascript generation by ASP.NET menu control

In my website I'm using the standard ASP.NET menu control. I already got so far as to write a custom control adapter to get rid of the rather tacky html output that is generated by the default control adapter.
One thing keeps buggering me though. Somehow ASP.NET is generating extra javascript that I don't want nor need for my menu controls, since I won't be using any of the dynamic features in the control. I replaced the control adapter, so it doesn't generate compatible HTML for that.
Anyone got an idea how I can prevent ASP.NET from generating the extra javascript for the menu control?
This problem cropped up for me after upgraded to ASP.net 4.0 with the installation of vs 2010. The fix is to either force the menu to render as a table or to turn off the new CSS/javascript "features" that 4.0 adds. Settings the menu's RenderingMode attribute to "Table" fixed this problem for me even though I use a Menu Adapter to render the control with lists.
<asp:Menu ID="mnuStuff" runat="server" RenderingMode="Table">
...
</asp:Menu>
You can do this site wide setting controlRenderingCompatibilityVersion to 3.5 in the web.config:
<system.web>
<pages controlRenderingCompatibilityVersion="3.5"/>
</system.web>
This will eliminate the rendering of inline javascript that asp injects in the base of the page.
If you prefer to stick with ASP.Net 4.0 control rendering you can create a custom menu (derived from System.Web.UI.WebControls.Menu) and replace the OnPreRender:
public class MyCustomMenu : Menu
{
protected override void OnPreRender(EventArgs e)
{
// Don't call base OnPreRender
//base.OnPreRender(e);
}
}
That did the trick.
An alternative way to get rid of the menu startup script is to call RegisterStartup script method before the Menu PreRender event, using the same script key, and outputting dummy (or empty) script.
This relies on internal implementation details of the Menu Type discovered using Reflector, so is somewhat fragile.
For example, a static class that looks something like:
static MenuHelper
{
private static Type _rendererType =
typeof(Menu).Assembly.GetType(
typeof(Menu).FullName + "+MenuRendererStandards"
);
public static void RemoveMenuScript(Menu menu)
{
string dummyScript = "<!-- Removed Menu Startup script -->";
string key = "_registerMenu_" + menu.ClientID;
ScriptManager.RegisterStartupScript(menu, _rendererType, key, dummyScript, false);
}
}
You then just need to make sure you call MenuHelper.RemoveMenuScript(menu) before the menu's PreRender event.
The OP is using an Adapter so Tim Santeford's answer is better in his situation. But if you want to render a static menu as a list without the startup code, and without the effort of writing an adapter, this might be an alternative.
<script type="text/javascript">
Sys.WebForms.Menu = "";
</script>
it works..
use it in aspx page
I just plan to ask about a similar question after 2 hours of search and have no luck.
What I want is to use the jquery superfish plugin as I want its animation for smooth looking. And with the ASP.NET generated javascript, the superfish just won't work.
And finally I try to set the ASP.NET Menu's control's attribute Enabled = false
and the outcoming source becomes this:
new Sys.WebForms.Menu({ element: 'mysitemeun', disappearAfter: 500, orientation: 'horizontal', tabIndex: 0, disabled: **true** });
After tracing the code, setting it disabled still have some style changes in the Menu but it will not add event to the MenuItem. And the superfish's animation works now.
if (!this.container.disabled) {
Sys.WebForms.Menu._domHelper.addEvent(this.element, 'mouseover', Sys.WebForms.MenuItem._onmouseover);
Sys.WebForms.Menu._domHelper.addEvent(this.element, 'mouseout', Sys.WebForms.MenuItem._onmouseout);
}

creating help for asp.net website

My requirement is to have database based help system for asp.net website, as shown in the image below. i have searched web but could not find even remotely related solution.
DNN Help System http://img3.imageshack.us/img3/6720/dnnhelpimage20091125.jpg
You could assign each help item a unique ID (perhaps GUID to make it easier to generate by the developer enabling help for that item).
Clicking on the link opens a dialog, tooltip, new window, whatever. Just have the UI load the help text by ID from the database.
To make this easier to implement in the UI, there are a few ways. Perhaps you can create a jQuery client-side behavior.
your HTML would look something like:
<span class="help" id="#{unique-id-here}">Admin</admin>
and you could have jQuery on DOM load:
$(function() {
var help = $(".help");
help.prepend("<img src=\"path/to/images/help.png\" />");
help.click(function() {
//do something with this.id; open a popup, a title bar, whatever.
}
});
We did it on our site by doing the following:
We have a HelpTopics database with a HelpTopicId and HelpTopicText
We create an aspx page that displays the HelpTopicText based on the HelptopicId passed in the querystring.
We set up a css class for the A tag that displays the link to the help with the question mark image.
We created a UserControl named TitleandHelp that contained a link to the page mentioned in step 2 and the style for the link set to step 3 above: The usercontrol has a public rpoperty for the title and one for the topicID (We called it HelpContext).
We add the usercontrol to the aspx page where appropriate
<uc2:titleandhelp ID="titleandhelp1" runat="server" HelpContext="4" PageTitle="Forgot Password" />
it may sound like a lot of work, but really it only takes a half hour or so to do all of the setup. The rest of the work lies in populating the table and dragging the usercontrol onto the pages where appropriate.

Resources