page 45 Httputility.htmlencode
page 56
To avoid needing to specify a fully qualifi ed type name for the model, you can make use of the @using declaration.
@using MvcMusicStore.Models @model IEnumerable<Album> <ul>
www.it-ebooks.info
Strongly Typed Views ❘ 57
@foreach (Album p in Model) { <li>@p.Title</li> } </ul>
An even better approach for namespaces, which you’ll end up using often in views, is to declare the namespace in the web.config file within the Views directory.
<system.web.webPages.razor> …
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="MvcMusicStore.Models" />
</namespaces> </pages> </system.web.webPages.razor>
page 56
To avoid needing to specify a fully qualifi ed type name for the model, you can make use of the @using declaration.
@using MvcMusicStore.Models @model IEnumerable<Album> <ul>
www.it-ebooks.info
Strongly Typed Views ❘ 57
@foreach (Album p in Model) { <li>@p.Title</li> } </ul>
An even better approach for namespaces, which you’ll end up using often in views, is to declare the namespace in the web.config file within the Views directory.
<system.web.webPages.razor> …
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Routing" />
<add namespace="MvcMusicStore.Models" />
</namespaces> </pages> </system.web.webPages.razor>
To see the previous
two examples in action, use NuGet to install the Wrox.ProMvc5.Views
.AlbumList package into a default ASP.NET MVC 5 project,
as follows:
Install-Package
Wrox.ProMvc5.Views.AlbumList
This places the two
view examples in the \Views\Albums folder and the controller code in the \
Samples\AlbumList
folder. Press Ctrl+F5 to run the project and visit /albums/listweaklytyped
and /albums/liststronglytyped to see the result of
the code.
Page 65
following Razor snippet?
@{ string rootNamespace = " MyApp"; }
< span >@ rootNamespace.Models </ span >
In this particular case, the hoped-for output was: < span > MyApp.Models </ span > Instead, you get an error that there is no Models property of string. In this admittedly edge case, Razor couldn’t understand your intent and thought that@ rootNamespace.Models was the code expression. Fortunately, Razor also supports explicit code expressions by wrapping them in parentheses: < span >@( rootNamespace). Models </ span > This tells Razor that.Models is literal text and not part of the code expression. While we’re on the topic of code expressions, we should also look at the case where you intend to show an e-mail address. For example, consider the following e-mail address: < span > support@ megacorp.com </ span >
Page 67
@{ string rootNamespace = " MyApp"; }
< span >@ rootNamespace.Models </ span >
In this particular case, the hoped-for output was: < span > MyApp.Models </ span > Instead, you get an error that there is no Models property of string. In this admittedly edge case, Razor couldn’t understand your intent and thought that@ rootNamespace.Models was the code expression. Fortunately, Razor also supports explicit code expressions by wrapping them in parentheses: < span >@( rootNamespace). Models </ span > This tells Razor that.Models is literal text and not part of the code expression. While we’re on the topic of code expressions, we should also look at the case where you intend to show an e-mail address. For example, consider the following e-mail address: < span > support@ megacorp.com </ span >
But, of course, what
if you really did mean for this to be an expression? For example, going back to
an earlier example in this section, what if you had the following list items:
<li>Item_@item.Length</li>
In this particular
case, that expression seems to match an e-mail address, so Razor will print it
out verbatim. But it just so happens that you expected the output to be
something like:
<li>Item_3</li>
Once again,
parentheses to the rescue! Any time there’s an ambiguity in Razor, you can use
parentheses to be explicit about what you want. You are in control.
<li>Item_@(item.Length)</li>
As mentioned earlier,
you can escape the @ sign with an @@
sign. This comes in handy when you need to display some Twitter handles, which
conventionally start with an @ sign:
<p>
You should follow
@aspnet </p>
Well, Razor is going
to attempt to resolve those implicit code expressions and fail. In the case
where you need to escape the @ sign, you can do so by using an @@
sign. Thus, this view becomes:
<p>
You should follow
@@aspnet </p>
Fortunately, the extra parentheses and escape
sequences are rarely needed. Even in very large applications these extra bits
of sequences might not be used at all. Rest assured that the Razor view engine
was designed with terseness in mind and that you won’t have to fight it to get
what you want, how you want it.
HTML Encoding
Given that many cases
exist where a view is used to display user input, such as a blog post comment
or a product review, the potential always exists for cross-site script
injection attacks (also known as XSS, which Chapter 7 covers in more detail).
The good news is that Razor expressions are automatically HTML encoded.
@{
string message =
"<script>alert('haacked!');</script>";
}
<span>@message</span>
This code does not
result in an alert box popping up but instead renders the encoded HTML:
<span><script>alert('haacked!');</script></span>
However,
in cases where you intend to show HTML markup, you can return an instance of System
.Web.IHtmlString
and Razor will not encode it. For example, all the view helpers discussed later
in this section return instances of this interface because they want HTML to be rendered
to the page. You can also create an instance of HtmlString
or use the Html.Raw convenience method:
@{
string message = "<strong>This is
bold!</strong>";
}
<span>@Html.Raw(message)</span>
This results in the
message being displayed without HTML encoding:
<span><strong>This
is bold!</strong></span>
Page 67
When setting variables
in JavaScript to values supplied by the user, using JavaScript string encoding
and not just HTML encoding is important. Use the @Ajax.JavaScriptStringEncode
to encode the input. Here’s the same code again using this method to better
protect against XSS attacks:
<script
type="text/javascript">
$(function () {
var message = 'Hello
@Ajax.JavaScriptStringEncode(ViewBag.Username)';
$("#message").html(message).show('slow'); });
</script>
Page 69
Unencoded Code Expression
In some cases, you
need to explicitly render some value that should not be HTML encoded. You can
use the Html.Raw method to ensure that the value is not
encoded.
<span>@Html.Raw(model.Message)</span>
Mixing Code and Plain Text
Mixing Code and Plain Text
Razor looks for the
beginning of a tag to determine when to transition from code to markup.
However, sometimes you want to output plain text immediately after a code
block. For example, the following sample displays some plain text within a
conditional block.
@if
(showMessage) {
<text>This is plain text</text>
} or
@if
(showMessage) { @:This is plain text. }
Server-Side Comment
Razor includes a nice
syntax for commenting out a block of markup and code.
@*
This is a
multiline server side comment.
@if
(showMessage) {
<h1>@ViewBag.Message</h1> }
All of this
is commented out.
*@
Calling a Generic Method
And as you’ve learned,
angle brackets cause Razor to transition back to markup unless you wrap the
whole expression in parentheses. @(Html.SomeMethod<AType>())
Page 70-72
Layouts
Layouts in Razor help
maintain a consistent look and feel across multiple views in your application.
If you’re familiar with Web Forms, layouts serve the same purpose as master
pages, but offer both a simpler syntax and greater flexibility.
SiteLayout.cshtml:
<!DOCTYPE
html>
<html>
<head><title>@ViewBag.Title</title></head>
<body>
<h1>@ViewBag.Title</h1>
<div
id="main-content">@RenderBody()</div> <footer>@RenderSection("Footer")</footer>
</body>
</html>
Option 1
<footer>@RenderSection("Footer",
required: false)</footer>
Option 2
<footer>
@if (IsSectionDefined("Footer")) {
RenderSection("Footer");
}
else {
<span>This is the default
footer.</span>
}
</footer>
@{
Layout =
"~/Views/Shared/SiteLayout.cshtml";
ViewBag.Title = "The Index!"; }
<p>This
is the main content!</p>
Page 73
When you create a
default ASP.NET MVC project, you’ll notice a _ViewStart.cshtml
fi le is already in the Views directory. It specifi es a default layout:
@{
Layout =
"~/Views/Shared/_Layout.cshtml"; }
SPECIFYING
A PARTIAL VIEW
The partial view
itself looks much like a normal view, except it doesn’t specify a layout:
<h2>@ViewBag.Message</h2>
Install-Package
Wrox.ProMvc5.Views.SpecifyingViews
This adds a sample
controller to your project in the samples directory with multiple action
methods, each specifying a view in a different manner. To run each sample
action, press Ctrl+F5 on your project and visit:
➤ /sample/index
➤ /sample/index2
➤ /sample/index3
➤ /sample/partialviewdemo
No comments:
Post a Comment