MVC Login Page with Custom Layout and ViewStart - asp.net-mvc

I have a problem I cannot wrap my head around, it is driving me crazy. I used the default template for MVC projects in VS2013 and everything works fine. I can login with users I've created using the Forms Authentication, etc. The problem I have is that when I drop a _ViewStart into the Account views folder, and use a custom layout for the login pages ... I keep getting redirected to the login page everytime I try to login. My Login Post method is also not being called, only the Default Login ActionResult fires. If I take the ViewStart file out and use the default layout, I have no problems.
Here is my _LoginLayout.cshtml
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Corporate</title>
<link rel="stylesheet" type="text/css" href="~/Content/style.css">
#Scripts.Render("~/bundles/modernizr")
#Scripts.Render("~/Scripts/jquery-1.10.2.min.js")
</head>
<body>
<div class="holder login">
<div class="row">
<div class="col-lg-5 left">
<img src="~/images/logo.png" alt="logo" />
</div>
</div>
<div class="row">
<div class="col-lg-6 border">
<img src="~/images/corporate.png" alt="corporate" />
<br />
<form>
#RenderBody()
</form>
</div>
</div>
<footer>
<p>© #DateTime.Now.Year - Application. All Rights Reserved.</p>
</footer>
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/bootstrap")
#RenderSection("scripts", required: false)
</div>
</body>
</html>
Here is the ViewStart...
#{
Layout = "~/Views/Shared/_LoginLayout.cshtml";
}
The login page is basically the same boiler plate page provided when you start the project. Everything works until I start trying to use a custom layout and viewstart.

Ok. I'm dumb.
#using (Html.BeginForm("Login", "Account",....
Creates Form tags. My layout had Form tags wrapping the RenderBody(). I was essentially nesting form tags which is a nono. Mystery solved.
It's the little things that get you.

Related

Overloading blocks with dust.js for nested templates

I have a layout called layouts/master.dust
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>{+title /}</title>
<link rel="stylesheet" href="css/app.css" />
</head>
<body>
<div id="wrapper">
<h3>This is the master header</h3>
{+body /}
</div>
</body>
</html>
I then have a template called index.dust:
{>"layouts/master" /}
{<body}
<h1>{#pre type="content" key="greeting"/}</h1>
{/body}
Predictably, that outputs
This is the master header
Hello, Alex!
(when supplied with the relevant json)
My issue is, I'm creating another "nested" or "child" template: layouts/admin.dust that looks like:
{>"layouts/master" /}
<h4>This is an admin header</h4>
{+body /}
and a template adminIndex.dust that uses layouts/admin/dust like this:
{>"layouts/admin" /}
{<body}
<p>This is some stuff for admin</p>
{/body}
My problem, is the output is:
This is the master header
This is some stuff for admin
This is an admin header
This is some stuff for admin
So, my {+body} block is being called twice, and not overridden by my nested template
Is there a way to do that?
Edit
As per my comment, a more 'realistic' example of admin.dust would be:
{>"layouts/master" /}
<h4>This is an admin header</h4>
<div style="float: left; width: 200px;">
<strong>left nav</strong>
<ul>
<li>Link one</li>
<li>Link two</li>
</ul>
</div>
<div style="float: right">
{+ body /}
</div>
Where by in templates that use the admin layout, their body is in a div floated right (for example)
Your {+body} block is being overridden by your {<body} inline partial in your adminIndex.dust template. The contents of an inline partial (in your case <p>This is some stuff for admin</p>) will be inserted wherever a block is found in your template. If you are hoping to have the master header be replaced by the admin header, you would need your templates to look like this:
layouts/master.dust
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>{+title /}</title>
<link rel="stylesheet" href="css/app.css" />
</head>
<body>
<div id="wrapper">
{+header}<h3>This is the master header</h3>{/header}
{+body /}
</div>
</body>
</html>
layouts/admin.dust
{>"layouts/master" /}
{+header}<h4>This is an admin header</h4>{/header}
adminIndex.dust requires no change.
Note: I have added a {+header} block to layouts/master.dust with a default value, and added a {header} inline partial and removed the {+body} block from layouts/admin.dust. This will output:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
<link rel="stylesheet" href="css/app.css" />
</head>
<body>
<div id="wrapper">
<h3>This is the admin header</h3>
<p>This is some stuff for admin</p>
</div>
</body>
</html>

Why won't JQuery Mobile toolbar appear

I am trying to create a mobile version of my site using JQuery Mobile. I'd like a fixed header toolbar and a fixed footer toolbar to appear on all pages. However, those portions of the page are instead being written out as simple HTML lists. Here is the relevant header code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<title>Nightscape Creations Wallpapers</title>
<link rel="stylesheet" href="themes/NCMobile.min.css" />
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.2/jquery.mobile.structure-1.3.2.min.css" />
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script>
</head>
<div data-role="header" data-position="fixed">
Back
<h1>Nightscape Creations</h1>
Home
<div data-role="navbar">
<ul>
<li>Live Wallpapers</li>
<li>Static Wallpapers</li>
<li>Products</li>
<li>About</li>
</ul>
</div>
</div>
This code is visible at www.NightscapeCreations.com on the mobile site.
It seems like the JQuery code is either not being included correctly or is not being initialized. I'm not sure if maybe I missed something obvious in the installation that I just need a second set of eyes on.
If it's relevant, the remainder of the page might be similar to:
<body>
<div data-role="page" id="home">
Some text
</div>
<div data-role="page" id="liveWallpapers">
Some text
</div>
<div data-role="page" id="products">
Some text
</div>
<div data-role="page" id="about">
Some text
</div>
<div data-role="page" id="staticWallpapers">
Some text
</div>
</body>
<div data-role="footer" data-position="fixed">
<h1>All images, animations, and content © Nightscape Creations</h1>
Visit Desktop Site
</div>
</html>
EDIT 1
Per a suggestion by mwfire I have moved all of my visible code inside of the body tags. A simplified version of the page is now available with this code:
<!DOCTYPE html>
<html>
<head>
<title>Nightscape Creations Wallpapers</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="stylesheet" href="themes/NCMobile.min.css" />
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.2/jquery.mobile.structure-1.3.2.min.css" />
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script>
</head>
<body>
<div data-role="header" data-position="fixed">
Back
<h1>Nightscape Creations</h1>
Home
<div data-role="navbar">
<ul>
<li>Live Wallpapers</li>
<li>Static Wallpapers</li>
<li>Products</li>
<li>About</li>
</ul>
</div>
</div>
<div data-role="page" id="home1">
<div style="font-weight:bold; text-decoration:underline;">Welcome</div>
Welcome to Nightscape Creations Mobile. Here you will find animated live wallpapers, static wallpapers, and links to physical products
with the wallpaper images included. Use the header button above to browse the mobile site, or
click here to visit the main site instead.
</div>
<div data-role="footer" data-position="fixed">
<h1>All images, animations, and content © Nightscape Creations</h1>
Visit Desktop Site
</div>
</body>
</html>
However, this does not cause the toolbars to appear.
Actually all your HTML code belongs inside the body tag. I bet you don't see any footer as well ;)
Edit
Just to clarify, the structure is supposed to be like that:
<!DOCTYPE ...>
<html>
<head>
<title>Page title</title>
</head>
<body>
<!-- All visible HTML content goes here! -->
</body>
</html>
No HTML tags should be outside the body tag (except head, body & Doctype).
You can find more on page structures here.
Edit2
In addition to this, header and footer are supposed to be inside the data-role="page" div. jQuery displays one page at a time, think of it as a single HTML page. It has to include the complete structure of a single page (if you want header and footer, of course), like:
<div data-role="page">
<div data-role="header">
<h1>Test</h1>
</div>
<div data-role="content">
Content
</div>
<div data-role="footer">
<h3>Footer</h3>
</div>
</div>

Custom jQuery Mobile Select menu

I'm working on my first app in jQuery Mobile. I'm stuck on a select menu.
I've tried to copy/paste the "Your state" style at http://jquerymobile.com/demos/1.2.0/docs/forms/selects/custom.html and work it into my code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CAST</title>
<link rel="stylesheet" href="./custom.css" />
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css" />
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script>
<script src="./global.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
</head>
<body>
<div data-role="page" data-theme="c" id="home-page" class="type-interior" data-url="home-page">
<div data-role="header" style="background:#AAA">
<h1><img src="/logo.png" width="97" height="50" border="0" /></h1>
</div>
<h2 id="header_title"></h2>
<div id="error" class="error" style="display:none;">Could not connect to the server. Please try again.</div>
<div data-role="content">
<div class="content-primary" id="content">
<div data-role="fieldcontain">
<label for="client" class="select">Client:</label>
<select name="client" id="client" data-native-menu="false">
<option value="1">Option 1</option>
</select>
</div>
</div>
</div>
<div data-role="footer">
<h4>© 2013</h4>
</div>
</div>
</body>
</html>
The select menu shows up, but it doesn't look like the custom mobile version on their site? It just looks like a regular select menu.
I don't understand enough jquery.mobile yet to really even know how to ask this question properly... but any help getting this to work would be appreciated!
If you mean the "Your state" example looks like a dialog, showing the contents of the menu alone in the screen, you have to add more options to the select element as it is stated in the page you link:
When it has too many options to show on the device's screen, the framework will automatically create a new "page" populated with a standard listview for the options. This allows us to use the native scrolling included on the device for moving through a long list. The text inside the label is used as the title for this page.
I modified the jsfiddle provided by Omar to add more options and it looks exactly like in the original site
<Ignore>Code so I can post link to jsfiddle</ignore>

MVC4 site and CNAME - only showing #RenderBody content

I just deployed my MVC4-.Net4.0 website to http://regatta.azurewebsites.net/
This works nicely - the jQuery and jQueryMobile scripts renders this perfectly.
I then followed the instructions and added my own domain - http://regatta.albrektsen.net and configured my dns supplier with both a CNAME and an A record pointing to azure.
This again works fine - I get to http://regatta.albrektsen.net - and the site comes up.
However: When accessing my custom domain, I only get the stuff rendered by #RenderBody()
Basically the
<head>
<meta charset="utf-8" />
<title>#ViewBag.Title</title>
<meta name="viewport" content="width=device-width" />
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
#Styles.Render("~/Content/mobileCss", "~/Content/css")
#Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div data-role="page" data-theme="b" #TempData["DataUrl"]>
<div data-role="header">
#if (IsSectionDefined("Header")) {
#RenderSection("Header")
} else {
#Html.ActionLink("Home", "Index", "Home");
<h1>#ViewBag.Title</h1>
#Html.Partial("_LoginPartial")
}
</div>
<div data-role="content">
#RenderBody()
</div>
</div>
Is missing when accessing my custom domain - only the stuff displayed by #RenderBody is shown.
How is this possible? What am I doing wrong?
Oops - embarassing...
Actually - this turned out to be a problem with my PC's DNS cache.
Issuing ipconfig /flushdns (With admin privileges) solved the issue. My "local" regatta.albrektsen.net was pointing to a test server.

jQuery Mobile layout in ASP.NET MVC app

Short:
Do you put the data-role portions (header|content|footer) in your layout/master page or in each view in ASP.NET MVC?
Long:
Trying to find the 'best practice' with handling jQuery mobile layout. The docs (and some others) show:
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
...
</head>
<body>
<div data-role="page">
<div data-role="header">...</div>
<div data-role="content">#RenderBody()</div>
<div data-role="footer">...</div>
</div>
</body>
</html>
However I have seen this too :
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
...
</head>
<body>
<div data-role="page">
#RenderBody()
</div>
</body>
</html>
With each view having:
<div data-role="page">
<div data-role="header">...</div>
<div data-role="content">...</div>
<div data-role="footer">...</div>
</div>
So, do you define the header|content|footer in each 'view' in ASP.NET or in the layout/master? Is one better? Does it matter at all?
I've noticed that navigation (using the back button) only works correctly when you use the first option (DRY). I am facing the same issue. If I want different header content how do you change this if you have one layout page. I think the way to go is to create sections in the master layout page and enable them per view as required.
RenderSection("SectionName")
Personally, I've been using the second practice for Don't-Repeat-Yourself sake.

Resources