European Windows 2012 Hosting BLOG

BLOG about Windows 2012 Hosting and SQL 2012 Hosting - Dedicated to European Windows Hosting Customer

European ASP.NET MVC 3 Hosting :: Nested Layout Pages with Razor

clock July 20, 2011 05:16 by author Scott

Razor Layout pages are the equivalent to MasterPages in ASP.NET Web Forms and the Web Forms View Engine within ASP.NET MVC. Just as it is possible to nest MasterPages, it is also possible to nest Razor Layout pages. This article explores the process required to achieve nesting of Layout pages using the Razor View Engine in MVC 3, or WebMatrix Web Pages sites.

You would consider using nested layout pages if you were building a corporate site for a global company, for instance, which is comprised on many divisions, each having their own look and feel. There may be a common look and feel for the header and footer of the site, but the navigation and content changes in both structure and appearance depending on which division of the company is being featured. The imaginary company that the sample site relates to has a number of divisions, one of which is Automation and another for Electronics. Each of them has their own branding which needs ot be catered for. For simplicity's sake the following walkthrough illustrates the use of Razor in a Web Pages site built using WebMatrix, but the principals are exactly the same if you are using ASP.NET MVC 3.

Step 1

Create a new site using the Empty Site template and name this Nested Layouts. Add two folders to the site – one called Content and the other called Shared. Add a new CSS file to Content and leave it with the default file name of StyleSheet.css. Add the following code to it:

body {
    font-family: Arial, Helvetica, sans-serif;
    font-size: 80%;
    padding: 0;
    margin: 0;
}

h1{
    color: #0093c0;
}

#wrapper{
    background-color: #c1dfde;
    padding: 10px;
    width: 800px;
    margin: auto;
    min-height: 600px;
}

#electronics, #automation{
    min-height: 400px;
}

#electronics{
    background-color: #8ec1da;
    width: 650px;
    float: left;
}

#automation{
    background-color: #ffe8d3;
}

#electronicsnav{
    background-color: #fff;
    min-height: 400px;
    width: 150px;
    float: left;
}

#automationnav{
    background-color: #dedede;
}

#automation h3{
    color: #997d63;
}

Step 2

Add a CSHTML file to the Shared folder and name it _MainLayout.cshtml.  Change the existing code so that it looks like this:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>@Page.Title</title>
        <link href="@Href("~/Content/StyleSheet.css")" rel="stylesheet" type="text/css" />
    </head>
    <body>
        <div id="wrapper">
            <div id="header"><h1>Global Enterprises</h1></div>
            <div id="nav">
                <a href="Home">Home</a> |
                <a href="About">About</a> |
                <a href="Engineering">Engineering</a> |
                <a href="Electronics">Electronics</a> |
                <a href="Automation">Automation</a> |
                <a href="Contact">Corporate</a> |
                <a href="Contact">Contact Us</a>
            </div>
                @RenderBody()
        </div>
    </body>
</html>

Step 3

Add another CSHTML file to the Shared folder and name this one _AutomationLayout.cshtml. Replace the existing code with this:

@{
    Layout = "~/Shared/_MainLayout.cshtml";
}
<div id="automationnav">
    <a href="Products">Products</a> |
    <a href="Services">Services</a> |
    <a href="Support">Support</a> |
    <a href="Team">The Team</a> |
</div>
<div id="automation">
    @RenderBody()
</div>
<div id="footer">The Automation Division Footer</div>

Step 4

Now add a third CSHTML file to the Shared folder. Name it _ElectronicsLayout.cshtml, delete the existing code and add the following:

@{
    Layout = "~/Shared/_MainLayout.cshtml";
}
<div id="electronicsnav">
    <a href="Products">Products</a> <br />
    <a href="Services">Services</a> <br />
    <a href="Support">Support</a> <br />
    <a href="Team">The Team</a> <br />
</div>
<div id="electronics">
    @RenderBody()
</div>
<div id="footer">The Electronics Division Footer</div>

Step 5

Add a CSHTML file to the root folder. Name this one Automation.cshtml and replace the existing code with this:

@{
    Layout = "~/Shared/_AutomationLayout.cshtml";
    Page.Title = "Automation";
}
<h3>Automation Home Page</h3>

Step 6

Finally, add another CSHTML file to the root folder and call it Electronics.cshtml. Replace the existing code with the following:

@{
    Layout = "~/Shared/_ElectronicsLayout.cshtml";
    Page.Title = "Electronics";
}
<h3>Electronics Home Page</h3>

Making sure that the Electronics page is selected in the left pane, click the Run button to launch the page in your browser. Notice that the second navigation has a white background and the main area has a blue background. Click the Automation link in the top navigation. See how the colours change? The main content is a brownish-pink colour as is the secondary navigation. The heading in the main content area changes colour too. Most obviously, the Electronics navigation is displayed vertically whereas the Automation navigation is horizontal.





What defines a Layout page is a call to the RenderBody method. In this exercise you created a layout page from _MainLayout.cshtml by placing @RenderBody() in the file, and by matching that with Layout declarations in both the _AutomationLayout.cshtml and ElectronicsLayout.cshtml files. You also added calls to RenderBody in both of those files, thus turning them into layout pages. Electronics.cshtml and Automation.cshtml each contained Layout declarations pointing to their own layout page, completing the content – layout relationship. There is no limit to the number of levels to which you can nest layout pages.

The design of the pages won’t win any awards, but this sample serves to illustrate that nesting layout pages can offer a very flexible solution to certain problems.



European ASP.NET MVC 3 Hosting :: Remote Validation in ASP.NET MVC 3 RC1

clock June 22, 2011 05:55 by author Scott

Remote validation has finally landed in RC1 of ASP.NET MVC 3.  It’s a weird area as more often than not people tend to over complicate something that is really pretty simple.  Thankfully the MVC implementation is fairly straightforward by simply providing wiring allowing the jQuery Validation plugin to work it's magic.  Basically there is a new Remote attribute that can be used like so.

public class Credentials
{   
    [Remote("Username", "Validation")]
    public string Username { get; set; }    

    public string Password { get; set; }
}

As you can see we have attributed the Username field with a Remote attribute.  The 2 parameters tell us what Action and Controller we should call to perform the validation.  This does make me feel slightly uneasy as it kind of feels like you are coupling the controller to the model which doesn't sit right by me.  currently sitting on the fence I'll see how it works in real life.  Anyway I implemented it like so,

public class ValidationController : Controller
{    public ActionResult Username(string UserName)
    {
        return Json(Repository.UserExists(Username), JsonRequestBehavior.AllowGet);
    }
}

And thats you - provided you have the necessary client side libraries included of course (jQuery, jQuery Validate etc). and have Client Side Validation turned on (now by default in MVC3).


Configuration

The Remote attribute offers a few nice little configuration options to make things easier.  The typical ones are there such as ErrorMessage, ErrorResource etc. but there are a few specific ones as well.

Fields

There may be a case where ding the name and the value of a single form field isn’t enough to perform validation.  Perhaps validation is affected by some other field/value in the form.  The Remote attribute accepts a comma separated list of other fields that need to be sent up with the request using the Fields parameter

This basic example will send up the value of the EmailService input field along with the value of Username.  Clean and simple.

[Remote("Username", "Validation", Fields = "EmailService")]

HttpMethod

HttpMethod simply allows us to change how the ajax request is sent e.g. via POST or GET or anything else that makes sense.  So to send a remote request via POST

[Remote("Username", "Validation", HttpMethod = "POST")]

A Minor Difference

You might notice if you read the release notes for RC1 that my implementation of the controller is slightly different.  The reason being that the example in the release notes is broken :-).  The example looks like this

public class UsersController {
    public bool UserNameAvailable(string username) {
        return !MyRepository.UserNameExists(username);
    }
}

However the Validate plugin expects a JSON response which is fine on the surface but returning a boolean response to the client side results in a response body of False (notice the captial F) which in turn causes a parse error when the plugin performs JSON.parse.  My suggested solution is actually more inline with how most people would typically write an Ajax capable controller action anyway (though I am not happy with the JsonRequestBehaviour usage) but there are other ways but they aren’t pretty….

public class ValidationController : Controller
{       
    public string Username(string username)
    {
        return (!Repository.UserExists(Username)).ToString().ToLower();
    }
}

See?  Ugly and plain WRONG (but it will work).

Nice to see this feature finally landing as it can be useful in certain situations.



About HostForLIFE.eu

HostForLIFE.eu is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2016 Hosting, ASP.NET Core 2.2.1 Hosting, ASP.NET MVC 6 Hosting and SQL 2017 Hosting.


Tag cloud

Sign in