Background
I have a problem regarding bundling and redirection in an MVC site. The site project consists of desktop version in default route and mobile friendly theme in a separate area. Both themes use bundling configuration as shown below.
// BundleConfig.cs
using System.Web.Optimization;
public class BundleConfig
{
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-*"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate*"));
bundles.Add(new ScriptBundle("~/bundles/jquerymobile").Include(
"~/Scripts/jquery-1.*", "~/Scripts/jquery-ui-1.*", "~/Scripts/jquery.mobile-{version}.js"));
bundles.Add(new StyleBundle("~/Content/jquerymobile/css").Include(
"~/Content/jquery.mobile-{version}.css"));
bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/Site.css"));
bundles.Add(new StyleBundle("~/Content/themes/base/css").Include(
"~/Content/themes/base/jquery.ui.core.css",
"~/Content/themes/base/jquery.ui.resizable.css",
"~/Content/themes/base/jquery.ui.selectable.css",
"~/Content/themes/base/jquery.ui.accordion.css",
"~/Content/themes/base/jquery.ui.autocomplete.css",
"~/Content/themes/base/jquery.ui.button.css",
"~/Content/themes/base/jquery.ui.dialog.css",
"~/Content/themes/base/jquery.ui.slider.css",
"~/Content/themes/base/jquery.ui.tabs.css",
"~/Content/themes/base/jquery.ui.datepicker.css",
"~/Content/themes/base/jquery.ui.progressbar.css",
"~/Content/themes/base/jquery.ui.theme.css"));
}
}
The bundle registered in Global.asax as this:
// Global.asax
protected void Application_Start()
{
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Note that I use different jQuery version for desktop (currently 3.1.1) and mobile theme (currently 1.12.4) due to "bind not a function" error in jquery.mobile-1.4.5
if version 3 being used (details).
The Layout view for both themes are given below:
Desktop (with DevExpress themes)
@using System.Web.Optimization
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, user-scalable=no, maximum-scale=1.0, minimum-scale=1.0" />
<title>@ViewBag.Title</title>
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
@{
Scripts.Render("~/bundles/jquery");
Scripts.Render("~/bundles/jqueryval");
Styles.Render("~/Content/css");
}
@Html.DevExpress().GetStyleSheets(
new StyleSheet { ExtensionSuite = ExtensionSuite.NavigationAndLayout },
new StyleSheet { ExtensionSuite = ExtensionSuite.Editors },
new StyleSheet { ExtensionSuite = ExtensionSuite.HtmlEditor },
new StyleSheet { ExtensionSuite = ExtensionSuite.GridView },
new StyleSheet { ExtensionSuite = ExtensionSuite.CardView },
new StyleSheet { ExtensionSuite = ExtensionSuite.PivotGrid },
new StyleSheet { ExtensionSuite = ExtensionSuite.Chart },
new StyleSheet { ExtensionSuite = ExtensionSuite.Report },
new StyleSheet { ExtensionSuite = ExtensionSuite.Scheduler },
new StyleSheet { ExtensionSuite = ExtensionSuite.TreeList },
new StyleSheet { ExtensionSuite = ExtensionSuite.RichEdit },
new StyleSheet { ExtensionSuite = ExtensionSuite.Spreadsheet },
new StyleSheet { ExtensionSuite = ExtensionSuite.SpellChecker }
)
@Html.DevExpress().GetScripts(
new Script { ExtensionSuite = ExtensionSuite.NavigationAndLayout },
new Script { ExtensionSuite = ExtensionSuite.HtmlEditor },
new Script { ExtensionSuite = ExtensionSuite.GridView },
new Script { ExtensionSuite = ExtensionSuite.CardView },
new Script { ExtensionSuite = ExtensionSuite.PivotGrid },
new Script { ExtensionSuite = ExtensionSuite.Editors },
new Script { ExtensionSuite = ExtensionSuite.Chart },
new Script { ExtensionSuite = ExtensionSuite.Report },
new Script { ExtensionSuite = ExtensionSuite.Scheduler },
new Script { ExtensionSuite = ExtensionSuite.TreeList },
new Script { ExtensionSuite = ExtensionSuite.RichEdit },
new Script { ExtensionSuite = ExtensionSuite.Spreadsheet },
new Script { ExtensionSuite = ExtensionSuite.SpellChecker }
)
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
</head>
<body>
<div>
<form id="form1" enctype="multipart/form-data" method="post">
@Html.DevExpress().Splitter(settings =>
{
settings.Name = "MainSplitter";
settings.AllowResize = false;
settings.Orientation = System.Web.UI.WebControls.Orientation.Vertical;
settings.FullscreenMode = true;
settings.SeparatorVisible = false;
settings.Styles.Pane.Border.BorderWidth = System.Web.UI.WebControls.Unit.Pixel(0);
settings.Styles.Pane.Paddings.Padding = System.Web.UI.WebControls.Unit.Pixel(0);
settings.Theme = AristaHRM.Theme.SelectTheme;
settings.Panes.Add(pane =>
{
pane.Name = "Header";
pane.PaneStyle.BorderBottom.BorderWidth = System.Web.UI.WebControls.Unit.Pixel(1);
pane.PaneStyle.CssClass = "headerPane";
pane.SetContent(() =>
{
Html.RenderPartial("HeaderPartialView", HeaderViewRenderMode.Full);
});
});
settings.Panes.Add(pane =>
{
pane.Name = "Content";
pane.AutoHeight = true;
pane.PaneStyle.CssClass = "mainContentPane";
pane.MinSize = System.Web.UI.WebControls.Unit.Pixel(375);
pane.ScrollBars = ScrollBars.Auto;
pane.PaneStyle.BackColor = System.Drawing.Color.White;
pane.PaneStyle.BorderBottom.BorderWidth = System.Web.UI.WebControls.Unit.Pixel(1);
pane.SetContent(RenderBody().ToHtmlString());
});
settings.Panes.Add(pane =>
{
pane.Name = "Footer";
pane.Size = System.Web.UI.WebControls.Unit.Pixel(45);
pane.PaneStyle.CssClass = "footerPane";
pane.SetContent(() =>
{
Html.RenderPartial("FooterPartialView");
});
});
}).GetHtml()
</form>
</div>
</body>
</html>
Mobile (with jQuery mobile themes)
@using System.Web.Optimization
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>@ViewBag.Title</title>
@{
@Scripts.Render("~/bundles/jquerymobile");
@Scripts.Render("~/bundles/jqueryval");
@Styles.Render("~/Content/themes/base/css");
@Styles.Render("~/Content/jquerymobile/css");
}
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
</head>
<body>
<div data-role="page" data-theme="b" style="overflow:scroll">
<div data-role="header">
<h1>Mobile HRM</h1>
</div>
<div data-role="header" style="text-align:center">
@if (IsSectionDefined("Title"))
{
@RenderSection("Title")
}
</div>
<div data-role="content" style="overflow:scroll">
@RenderBody()
</div>
<div data-role="footer" style="text-align:center">
@* this link redirects to Desktop theme as root site *@
@Html.ActionLink("Desktop View", "Index", "Home", new { area = "" }, new { id = "button" })
</div>
</div>
<script type="text/javascript">
$(document).on('mobileinit', function () {
$.mobile.ajaxEnabled = false;
});
$(document).on('pageshow', '[data-role=page]', function () {
$(window).resize();
});
</script>
@RenderSection("Scripts", required: false)
</body>
</html>
Problem Statement
With above setup, I successfully entered mobile area with URL /Mobile/Home/Index
(note that mobile area index page uses mobile layout). However, when I tried to switch into Desktop theme through "Desktop View" link, I got error in console:
which checked in Debugger tab refers to window.execScript
:
( window.execScript || function( data ) {
window[ "eval" ].call( window, data ); // jscs:ignore requireDotNotation
})( data );
But if I clicked error link on the right provided in console (see image above), it shows a view source page with some error details inside:
System.Web.HttpException: A potentially dangerous Request.Path value was detected from the client (>).
[HttpException (0x80004005): A potentially dangerous Request.Path value was detected from the client (>).]
at System.Web.HttpRequest.ValidateInputIfRequiredByConfig() +9560004
at System.Web.PipelineStepManager.ValidateHelper(HttpContext context) +53
How can I solve this area redirection issue?
NB: I searched message given in exception detail (see results) and suspecting illegal characters submitted when redirecting to root site, but I can't figured out which part of mobile layout page caused the problem.
In jQuery Mobile framework, to enable animated page transitions, all links that point to an external page will be loaded via Ajax. The framework parses the link's href to formulate an Ajax request. All this is done automatically by jQuery Mobile. I think this mechanism could be the cause of your problem.
You could try to add attribute data-ajax="false" to "Desktop" link. It will cause a full page refresh with no animated transition.
@Html.ActionLink("Desktop View", "Index", "Home", new { area = "", }, new { id = "button", data_ajax = "false" })