Can a Url.Action specify a route in MVC5? - asp.net-mvc-5

In our default layout we have our logo wrapped with a URL.Action to navigate back to the home screen. However, if we are in an Area, it tries to navigate to the home controller in that area, which doesn't exist.
Our home controller is Submission. Here is the link in the layout file:
<a class="navbar-brand custm-navbar-brand" href="#Url.Action("Index", "Submission")">
<img src="#Url.Content("~/Content/images/eed-main-logo.png")" alt="E-Editorial Discovery" width="335" height="56">
</a>
If I am in an area like this: /Admin/Security/Index
the above link tries to go to: /Admin/Submission/Index
but it should go to: /Submission/Index
I'm sure there's a better way, but I haven't found it yet.

Specify the area like you would a parameter. So your first line should be:
<a class="navbar-brand custm-navbar-brand" href="#Url.Action("Index", "Submission", new { Area = "AreaName" })">

You could specify the area in the Url.Action call but this can get messy.
Rather than having to specify the area, why not sort the route out itself so it knows to tie it down to that namespace:
context.MapRoute("ExpressCheckoutRoute",
"expresscheckout/stage/{stageName}/{id}",
new { controller = "ExpressCheckout", action = "Stage", area = "FrontEnd", id = UrlParameter.Optional },
new[] { "Web.Areas.FrontEnd.Controllers" }
).DataTokens["UseNamespaceFallback"] = false;
This sorted the issue out for me and I no longer have to specify the area paramter (take note of the last 2 parts to that mapping).

Related

Orchard CMS - create vertical Navigation Menu next to Home

I am new to Orchard and trying to figure out how it works code-wise.
So, I have created a custom Content Type through the code and i am able to create Content Items under this Content Type. i have the 'Show on the Menu' checkbox on the editor page of the Content item. But when I check it and select the menu to which i want this newly created custom item to be added, it gets added as a vertical menu item whereas i need it to be added as a vertical submenu to one of the root items.
Please find images which describe what is happening now and what I need.
Current behavior
Expected behavior
Product2 is a custom content item and should be added as a entry in the vertical menu as shown in the 2nd image
This task is rather complex. There are several steps involved.
Understanding how to create a child theme
See the official documentation, create a child theme and enable it
Understanding the concept of shape alternates
See the official documentation
Configure the menu in admin area
Go to the admin area, click on Navigation in the menu and add some menu items and sub items, for example
[ Home (Content Menu Item) ]
[ Service (Content Menu Item) ]
[ Document Storage (Custom Link) ]
Once you have this structure Orchard renders this structure via a #Zone(Model.Navigation) call in a theme. You have to search where this call is located for yourself, it depends on the theme.
My child theme uses a Layout.cshtml alternate which calls #Zone(Model.Navigation) where needed like so
#{
Func<dynamic, dynamic> Zone = x => Display(x); // Zone as an alias for Display to help make it obvious when we're displaying zones
}
<div class="wrapper">
#* Navigation bar *#
#if (Model.Navigation != null)
{
<div id="layout-navigation" class="group navbar navbar-default" role="navigation">
#Zone(Model.Navigation)
</div>
}
...
</div>
Now, if Orchard renders the menu itself, it uses the Menu.cshtml shape template, thus the next step will be to provide a shape alternate for Menu.cshtml.
Creating a shape alternate for the menu in your child theme
Go to you child theme folder and add a file Views\Menu.cshtml and start rendering the menu there, for example
<ul class="nav navbar-nav">
#DisplayChildren(Model)
</ul>
The #DisplayChildren(Model) call will start rendering the menu items via the MenuItem.cshtml shape template, thus the next step will be to provide a shape alternate for MenuItem.cshtml.
Creating a shape alternate for menu items in your child theme
Go to you child theme folder and add a file Views\MenuItem.cshtml and start rendering the menu items. Here is the content of my MenuItem.cshtml file, which renders the menu items as <li> structure according to the bootstrap specs:
#*
this shape alternate is displayed when a <li> element is rendered
whereas the following code is based on Orchard.Core\Shapes\Views\Menu.cshtml
*#
#{
// odd formatting in this file is to cause more attractive results in the output.
var items = Enumerable.Cast<dynamic>((System.Collections.IEnumerable)Model);
}
#{
if (!HasText(Model.Text)) {
#DisplayChildren(Model)
}
else {
if ((bool) Model.Selected) {
Model.Classes.Add("current");
}
if (items.Any()) {
Model.Classes.Add("dropdown");
}
#* morphing the shape to keep Model untouched*#
Model.Metadata.Alternates.Clear();
Model.Metadata.Type = "MenuItemLink";
#* render the menu item only if it has some content *#
var renderedMenuItemLink = Display(Model);
if (HasText(renderedMenuItemLink)) {
var tag = Tag(Model, "li");
#tag.StartElement
#renderedMenuItemLink
if (items.Any()) {
<ul class="dropdown-menu">
#DisplayChildren(Model)
</ul>
}
#tag.EndElement
}
}
}
You can also provide alternates to override specific menu item types like the Custom Link. The file would then be MenuItemLink.cshtml with a content like
#*
this shape alternate is displayed when menu link is _not_ of type "Content Menu Item" otherwise MenuItemLink-ContentMenuItem.cshtml is used
whereas the following code is based on Orchard.Core\Shapes\Views\MenuItemLink.cshtml
*#
<a href="#Model.Href" #if (Model.Item.Items.Length > 0) { <text>class="dropdown-toggle" data-toggle="dropdown"</text> }>#Model.Text</a>
As you can see, a lot of work but pretty flexible.

Main Menu Navigation Item not linked to a content item but collapsing a sub menu

I have got a multi level navigation in Orchard CMS which shows sub menu items on hovering. When I click, it opens a content menu item. This works well on a PC but not on a mobile device. In case of a mobile device or touch device in general it should collapse the menu instead of jumping to another page.
I am looking for an easy and clean approach to solve this.
Is there a way to create such a menu item only acting as an opener for the sub menu items instead of actually linking to a page?
Some background information: It is actually a theme based on twittter bootstrap 3
You can extend the MenuItem shape (~/Core/Shapes/Views/MenuItem.cshtml) to differentiate between parent and children
So first create under {YourTheme}/Views new view called MenuItem.cshtml and paste in the following code
#{
// odd formatting in this file is to cause more attractive results in the output.
var items = Enumerable.Cast<dynamic>((System.Collections.IEnumerable)Model);
}
#{
if (!HasText(Model.Text))
{
#DisplayChildren(Model)
}
else
{
if ((bool)Model.Selected)
{
Model.Classes.Add("current");
}
#* morphing the shape to keep Model untouched*#
Model.Metadata.Alternates.Clear();
if (items.Any())
{
Model.Classes.Add("dropdown");
Model.Metadata.Type = "MenuItemLinkParent";
}
else
{
Model.Metadata.Type = "MenuItemLink";
}
#* render the menu item only if it has some content *#
var renderedMenuItemLink = Display(Model);
if (HasText(renderedMenuItemLink))
{
var tag = Tag(Model, "li");
#tag.StartElement
#renderedMenuItemLink
if (items.Any())
{
<ul>
#DisplayChildren(Model)
</ul>
}
#tag.EndElement
}
}
}
Now just create another view called MenuItemLinkParent.cshtml and create simple hyperlink placeholder that doesn't link anywhere
<a>#Model.Text</a>
Now any MenuItem which becomes parent will lose it's href link (you can also edit html structure and classes this way, if necessary for bootstrap). Easy and clean enough? :)

Wordpress Technical Terms

I'm working on designing a site in WP, but I'm at a loss for the right words to google. What I'm looking for is a "text container that can be toggled". I have a syntax highlighting plugin for posting code, but I don't want the code to be visible in large blocks considering it may be a little distracting. I was wondering if anyone could link me to a plugin or give me the technical term for what I'm thinking of, where you can put the text in a group and then be able to toggle whether it is visible or not within the page.
It sounds like what you are looking for is simply applying a CSS class to the element and then using jQuery or some other JS library to toggle its visibility. Example below (code is not optimized in order to explain some of the concepts. This can, read "should", be cleaned up):
// This is HTML/CSS
<body>
...
<p>Here is some normal text.</p>
Show/hide source code for displayText method
<div class="source_code" id="source_code_for_displayText_method">
// Groovy code
...
public void displayText(String message) {
outputStream.write(message)
}
...
</div>
...
Show/hide source code for download method
<div class="source_code" id="source_code_for_download_method">
// Groovy code
...
GParsPool.withPool(threads) {
sessionDownloadedFiles = localUrlQueue.collectParallel { URL url ->
downloadFileFromURL(url)
}
}
...
</div>
...
Show/hide all source code sections
...
</body>
You can default all source code sections to hidden:
// This is CSS
.source_code {
display: hidden;
}
Then you would use JS to provide the toggle ability:
// This is JavaScript
// This toggles a specific section by using an id ("#") selector
$('#source_code_displayText_method_toggle_link').onClick(function() {
$('#source_code_for_displayText_method').toggle();
});
// This toggles all source code sections by using a class (".") selector
$('#source_code_all_toggle_link').onClick(function() {
$('.source_code').toggle();
});
Some thoughts:
If you toggle all sections, you need to determine what the current state is -- if some are currently shown and others hidden, this will invert each. If you want "hide all" and "show all", then use .hide() and .show() respectively.
If you are manually adding the source code sections and want semantic selectors, the above is fine. If you are building some kind of automation/tool to allow you to repeat this, you'll probably want to use generated ids and helper links, in which case it would look like:
.
// This is HTML/CSS
<body>
...
<p>Here is some normal text.</p>
Show/hide source code for displayText method
<div class="source_code" id="source_code_1">
// Groovy code
...
public void displayText(String message) {
outputStream.write(message)
}
...
</div>
...
Show/hide source code for download method
<div class="source_code" id="source_code_2">
// Groovy code
...
GParsPool.withPool(threads) {
sessionDownloadedFiles = localUrlQueue.collectParallel { URL url ->
downloadFileFromURL(url)
}
}
...
</div>
...
Show/hide all source code sections
...
</body>
With the JavaScript to handle id parsing:
// This is JavaScript
// This toggles a specific section by using a dynamic id ("#") selector
$('.source_code_toggle_link').onClick(function(elem) {
var id = $(elem).attr("id");
// Split on the _ and take the last element in the resulting array
var idNumber = id.split("_")[-1];
var codeBlock = $('#source_code_' + idNumber);
codeBlock.toggle();
});

How to extend Orchard navigation module to add images to menu items

UPDATE: I've changed the original question drastically based on Bertrand's suggestions and my own findings. Now it provides an incomplete solution in its text instead of my own blind meanderings and commentary on Orchard, which were completely WRONG!
I need to display a menu using images instead of text, one standard, and another for when hovered/selected. The requirements for the site states that the end-user should be able to manage the menu item images. The standard navigation module now provides an HTML menu item, which is not what the end user wants. The customer wants a very simple, intuitive interface for configuring the sites many menus, and all menus are image-based.
Based on Bertrand's advice, and after realizing that Content Menu Item IS A CONTENT TYPE, I've created a new Content Part in the Admin Interface (not by code, I only want to write code for parts and content types when ultimately needed... I really want to see how far I can go with Orchard just by using the admin interface and templating/CSSing).
So, I've created a Menu Image Part, with two Content Picker fields added to it: Image and Hover Image. Then I've added this part to the Content Menu Item in the Manage Content Items admin interface.
Since I didn't write a Driver for it, the Model passed to the menu item template does not have an easily accessible property like #Model.Href... I've overriden the MenuItemLink-ContentMenuItem.cshtml with the following code so far:
#using Orchard.Core.Common.Models
#using Orchard.ContentManagement
#{
var contentManager = WorkContext.Resolve<IContentManager>();
var itemId = Model.Content.ContentItem.ContentMenuItemPart.Id;
ContentItem contentItem = contentManager.Get(itemId);
ContentField temp = null;
var menuImagePart = contentItem.Parts.FirstOrDefault(p => p.PartDefinition.Name == "MenuImagePart");
if (menuImagePart != null)
{
temp = menuImagePart.Fields.First();
}
}
<span>#temp</span>
#Model.Text
This yields the expected title for the Menu in a link, with a span before it with the following text:
Orchard.Fields.Fields.MediaPickerField
So all the above code (get the current content manager and the id of the ContentItem representing the ContentMenuItemPart, then use the content manager to get ContentItem itself, then linqing over its Parts to find the MenuImagePart (I can't use Get to get it because it requires a type and the MenuImagePart is not a type, it was created in the admin interface), then finally getting the first field for debugging purposes (this should be the Image field of the MenuImagePart I've created...)... all the above code actually got me to the Media Picker Field on my Meny Image Part...
What I'm not being able to do, and what makes me certainly a lot obtuse and stupid, is to find a way to read the MediaPickerField URL property! I've tried casting it to MediaPickerField, but I can't access its namespace from inside my template code above. I don't even know which reference to add to my theme to be able to add the following directive to it:
#using Orchard.Fields.Fields
I've finally succeeded in this task (thanks to Bertrand's direction).
UPDATE: And thanks again to Bertrand I've polished the solution which was running in circles, querying content items from the content manager when they were already available on the Model... now I'm leveraging the dynamic nature of content item, etc. And I'm finally satisfied with this solution.
It was necessary to create a new Content Part called Menu Image, then add this to the Content Type named Content Item Menu, and finally overriding the Content Item Menu template. This last part was the really tricky one. If it was not for Bertrand's directions the code bellow would have been smelly and daunting. The template ended up as follow:
#using Orchard.Utility.Extensions;
#using System.Dynamic
#{
/* Getting the menu content item
***************************************************************/
var menu = Model.Content.ContentItem;
/* Creating a unique CSS class name based on the menu item
***************************************************************/
// !!! for some reason the following code throws: 'string' does not contain a definition for 'HtmlClassify'
//string test = menu.ContentType.HtmlClassify();
string cssPrefix = Orchard.Utility.Extensions.StringExtensions.HtmlClassify(menu.ContentType);
var uniqueCSSClassName = cssPrefix + '-' + Model.Menu.MenuName;
/* Adds the normal and hovered styles to the html if any
***************************************************************/
if (menu.MenuImagePart != null)
{
if (!string.IsNullOrWhiteSpace(menu.MenuImagePart.Image.Url))
{
using(Script.Head()){
<style>
.#uniqueCSSClassName {
background-image: url('#Href(menu.MenuImagePart.Image.Url)');
width: #{#menu.MenuImagePart.Image.Width}px;
height: #{#menu.MenuImagePart.Image.Height}px;
display: block;
}
</style>
}
}
if (!string.IsNullOrWhiteSpace(menu.MenuImagePart.HoverImage.Url))
{
using(Script.Head()){
<style>
.#uniqueCSSClassName:hover {
background-image: url('#Href(menu.MenuImagePart.HoverImage.Url)');
width: #{#menu.MenuImagePart.HoverImage.Width}px;
height: #{#menu.MenuImagePart.HoverImage.Height}px;
}
</style>
}
}
}
}
<a class="#uniqueCSSClassName" href="#Model.Href">#Model.Text</a>
The only thing that I didn't understand is why I can't use HtmlClassify as an extension method with menu.ContentItem.HtmlClassify() and have to resort to calling the method as a standard static method (see the line with the comment `// !!! for some reason the following code throws´...)
Thanks again Bertrand!

Spotify apps tabs - update cache

I'm trying to display a div inside tab playlists if the href contains a spotifyURI. This will be used to display a playlist under a tab.
Step by step this is my problem:
Click playlist tab and then click the "My playlist1".
The href is displayed in the playlist container under the tab playlists. (perfect so far)
Click the start tab and then click the playlists tab.
Instead of displaying the list of playlists the playlist container is show again. So the last used url is cached?
Then if the playlists tab is clicked again the url will be "reseted" and the list of playlists will be shown and playlist container hidden.
I'd like 4. to show the playlist list right away instead.
Is there a way to reset or what am I missing?
<script>
$(document).ready(function() {
sp = getSpotifyApi(1);
var m = sp.require("sp://import/scripts/api/models");
updateTabs();
m.application.observe(m.EVENT.ARGUMENTSCHANGED, updateTabs);
function updateTabs()
{
console.log(m.application.arguments);
var args = m.application.arguments;
$('.section').hide();
if (args[1] == "spotify") $("#playlist").html("args:"+args).show();
else $("#"+args[0]).show();
}
});
</script>
<div id="playlist" class="section">Container for playlist content</div>
<div id="start" class="section">Welcome</div>
<div id="playlists" class="section">
My playlist1
My playlist2
</div>
Thanks alot for all replys!
Here is how I will proceed using JQuery.
First of all you need to use the Localstorage :
var stor = sp.require("sp://import/scripts/storage");
Then if for exemple you get a list of playlist you can build the list like this
for (var i=0; i<d.playlists.length; i++) {
$('#playlists').append('My <a id="p' + i + '"href="'+ d.playlists[i] +'">playlist1</a>');
$('#playlists #p'+i).live('click', function(e) {
e.preventdefault();
stor.set('choosenplaylist', d.playlists[i]);
});
}
This was for the storage now for when changing tad :
if (!stor.get('choosenplaylist')=='') {
location.href=stor.get('choosenplaylist');
}
Okay this is a suggestion and it need to be tested regarding to your app.
Im trying this out now, and i can reproduce your bug (im guessing it's a bug, the tab should replace the url in my opinion)
But, until it's fixed, my best guess is to capture the playlist links in an event handler and cancelling the original event, after cancelling you replace the content with the appropriate playlist view.
Tab test code (on gist.github.com)
I've abstracted the actual view binding from the event handler, and added a click event hook that calls the abstract view binder instead of the "real" one, this also supports deep linking into the an app

Resources