Introducing MVC Development w/the Razor View Engine for Visual Studio Developers

The Razor View Engine is a precise, useful, light language that enables you to create views for MVC projects in ASP.NET still while keeping a separation of concerns, ability to test, and pattern based development.  ASP.NET MVC developers looking for a more concise syntax now have another option that’s built-in (of course, there are many 3rd party view engines out there) with the language being a familiar light version of C#.

The Razor View engine is used to create WebMatrix sites or Visual Studio MVC applications.  When using ASP.NET MVC with either engine, you’ll stick to a style of development called “convention over configuration”, meaning that you’ll use certain naming conventions to name files, models, views, controllers, and other key application elements rather than storing lots of metadata about these same elements in a configuration file.  When using MVC in Visual Studio 2010, it’s is setup so that you’ll be guided to use convention over configuration, which becomes evident when exploring an ASP.NET MVC project.

Getting Started

Before you start, go and download these two things (as of this post; things are subject to change – these could end up in VS at some point):

You can also find the Razor Syntax Highlighter by choosing Extensions Manager from the Visual Studio Tools menu.  Once installed, MVC 3 project templates are available from Visual Studio.  The MVC 3 Web Application template allows you to use either the Web Forms View Engine or the Razor View Engine, while MVC 2 Applications contain only the WF View Engine.

image_2

When creating a new MVC 3 project a new dialog box appears asking which application type, view engine, and testing framework you’d like to use.  You can and should add a test project so you can test your code, then actually write some tests in it.   The image below demonstrates selecting the internet application project template using Razor as the view engine, as well as the test framework.  The internet application MVC template adds in ASP.NET membership & security features to the project by creating the necessary model, view and controller for logging on and registering as a site user.

image_6

Verify that the project is created with three folders, one each for Models, Views, and Controllers which is the same folder structure as a MVC 2 site.  The project also contains auxiliary folders and files needed for the application such as the Content & App_Data folders.   Since this is an MVC application using the Razor View Engine, you will see a different file extension – .cshtml.  The .cshtml files are Razor View Pages written using the Razor View Engine.  If you’re not familiar with Razor syntax, I’ve blogged about it here, and the online documentation has more information as well.

image_11

The application template sets up some models, views and controllers to start with, and is now ready for new models, views, and controllers.  I’ve found the easiest way to work with MVC in VS is to start with the model, move to the controller, then create the view, so we’ll look at models first.

Models

A model is a representation of an underlying data store.  Models can be almost anything from any data source; EF or Linq2Sql Models, or a simple class.  The code the builds the model below consists of two classes, a ProductModel class and a Product class.  The ProductModel class returns a List<t> of Product objects in a property aptly named Products that represents one or more products in the data store .  Product objects contain ProductNumber, Name and Price properties and represent an individual product in the data store.  The model code representing these product objects is below:

using System.Collections.Generic;
namespace AdventureWorks.Models
{
    public class ProductModel
    {
        public List<Product> Products { get; set; }
        public ProductModel()
        {
            Products = new List<Product>();
            this.Products.Add(new Product("AB-00-J1" ,"Super Fast Bike" ,1000M));
            this.Products.Add(new Product("EE-9-OL"  ,"Durable Helmet"  ,123.45M));
            this.Products.Add(new  Product("MMM99-54" ,"Soft Bike Seat"  ,34.99M));
        }
    }

    public class Product
    {
        public Product(string productNumber, string name, decimal price)
        {
            Name = name;
            Price = price;       
            ProductNumber=productNumber;
        }
        public string ProductNumber { get; set; }
        public string Name { get; set; }
        public decimal Price { get; set; }
       
    }
}

Models are handed over to views by controllers so the views can render the data from the model.  The model will extend business logic (of course, this is a simple example, business logic will likely be spread out into other applications & tiers). Models also provide validation information to the view via metadata & code.  You can add the model to the Models folder or you can reference an external data model library.  In this case, the model’s been added to the Models folder.

Controllers

Controllers are objects that inherit from the System.Web.Mvc.Controller class that match models with views.  During incoming requests, MVC’s routing system kicks in and determines which controller method to use based on routing code set in the global.asax.cs file.  A default route is set in the global.asax.cs file that works for most of the routes you’ll need, however, if need be then you can modify/add/delete your own routes.

Staying within convention, controller code files should go in the Controllers folder. The controller class must follow the naming convention of YourNameController, i.e., ProductsController.  The controller’s Index method, again following convention, must be named the same name as its view but without the file extension.  By following this pattern, the controller can have multiple actions that deliver data to multiple views, making code easier to write, maintain, and test.

namespace AdventureWorks.Controllers
{
    public class ProductsController : Controller
    {
        public ActionResult Index()
        {
            ProductModel p = new ProductModel();           
            return View(p.Products);
        }
    }
}

By observing the previous code sample and the conventions that it follows, it’s clear that the Index method maps to the ViewsProductsIndex.cshtml view.  The Index() method’s return type is an ActionResult from the System.Web.Mvc namespace.  There’s many different results that you can use for different scenarios such as ContentResult, FileResult, RedirectResult, ViewResult and others depending on your view’s needs

Views

Views are a mechanism to format and render data in a browser from the model, as specified by the @model attribute (or @inherits) at the top of the view.  Views in ASP.NET MVC with either the ASPX or Razor View engines use a code-based way to render the page rather than relying on declarative controls, which create tight coupling and are hard to test.  Using the MVC approach creates cleaner output in the browser as well as cleaner and more terse syntax in the views as well.  Views are meant to only render the markup, code and data; they’re not meant as a place to store business logic. The model and tiers accessed by the model, are the appropriate places to host business logic.  The view can have a small amount of UI validation logic,as a first line of defense for input sanitation, e.g., required, regex and range validators.

To add a view to your project, right click on the controller and select Add View.

image_4

Visual Studio will need some information about the view, which is supplied in the Add View dialog box:

  1. Specify whether you want a strongly-typed view or not.  Creating a strongly-typed view allows you to refer to the underlying data structures in the classic object.property syntax.
  2. Specify the view data class.  The dropdown list displays classes in your project that are part of the data model.
  3. Specify the view engine.  ASPX and Razor are the options.
  4. Specify the view content.  Choices are list, details, edit. etc…  Choosing this option creates .cshtml or .aspx view pages that do page rendering for you.

image_12

Here’s what choosing these options will produce in a Razor view page named ViewsProductsIndex.cshtml:

@model List<AdventureWorks.Models.Product>
@{

View.Title = "Index";
Layout =
"~/Views/Shared/_Layout.cshtml"
;
}


<h2>Index</h2>
<
p>
@Html.ActionLink("Create New", "Create")
</p
>
<
table>
<tr>
<th>Edit/Details/Del</th>
<th>Product Number</th>
<th>Name</th>
<th>Price</th>
</tr>

@foreach (var item in
Model) {
<tr>
<td>
@Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
@Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
@Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
<td>
@item.ProductNumber
</td>
<td>
@item.Name
</td>
<td>
@String.Format("{0:F}", item.Price)
</td>
</tr>
}
</table>

Since the view is strongly typed, the data structure can be accessed as it is – an object with properties.  The code above loops through the model and renders a <TR> for each entity that the model holds along with <TD> tags and the actual data in them (ProductNumber, name and Price).  The result is a simple list of the three products in model with accompanying action links.

image_14

The HTML source shows a clean, precise table rendered to the browser.

image_8

Summary

Rendering a list of products is very easy using MVC and the Razor View Engine, as is updating/manipulating the data (logically what you’d do next if following this example).   If you’re digging deeper into learning MVC w/Razor the next topics you’ll want to get into are jQuery and HTML validation helpers for client side validation, and decorating the model with data annotations (also for validation).  The MVC web site has a ton of great examples and tutorials.

Although many ASP.NET MVC samples use the ASPX/Web Forms view engine they’re easily compared & converted to razor pages – so don’t avoid them, it’s still a great way to learn both MVC w/Razor and the ASPX engine.

Getting Familiar with Razor Language Syntax, Features and Rules

All languages have syntax rules, and ASP.NET Web Pages with Razor is no different.  The syntax is meant to be light and concise and simple, yet powerful enough to allow you to move to ASP.NET development using Visual Studio easily . Having said that, let’s take a look at a few key features of the language and some of the simple ways to write Razor code.

What exactly IS Razor and WebMatrix?

If you need the introduction on WebMatrix & Razor, no worries, I’ve already written a post on why, who and when WebMatrix & Razor are good choices and what they are intended for here.  Otherwise, continue on…

Basic Principles (Code/Script Blocks)

The @ character designates inline code, which is code that’s right inside of HTML  while the @{ with and ending } designates multiple lines of code.  Inline code can be anywhere – mixed inline with HTML, as HTML attribute values or page content. It can be multiple lines of code (a code block) as well when more functionality is needed.  Here’s a single inline statement sample with the actual code highlighted:

<li class=”price”>$@string.Format(“{0:f}”, p.Price)</li>

And here’s a what a block of code looks like:

@{

    LayoutPage = “~/_Layout.cshtml”;

    PageData[“Title”] = “Home”;

}

 

Each executable statement ends with a semicolon (;).Whitespace is ignored, but case is not.

Literal strings (or literal text) are put in double quotations (“), while numbers, if used mathematically, use none.

Comments

A Razor single line comment marker: @//

A Razor multi-line comment marker: @/* and */

Variables & Data Types

Use the var keyword to declare variables, or use the classic typed syntax.  The new operator is also supported.

var db = Database.Open(“bakery”);

string name = “Stephen”

int rating = 5;

var grid = new WebGrid(data, defaultSort: “Na
me”, rowsPerPage: 5);

Razor supports all the standard .NET framework simple data types and allows developers to take advantage of consuming objects and collections, using the classic dot notation, as shown below:

Mail.SmtpServer = “smtp.live.com”;

Mail.SmtpPort = 25;

Mail.EnableSsl = true;

Mail.Send(to: customerEmail, subject: “New Order”, body: body);

Paths

Use the ~ operator to get to the virtual root of the web site.  The virtual root is top level folder of your site, installed to here by default:

C:Users<YourUserName>DocumentsMy Web SitesBakery

Where <YourUserName> is your Windows login name.  The Server.MapPath() method is also available, to help you when you need to convert physical paths to virtual paths for use on a web server.

Code constructs

Razor supports conditions and loops, so you can make decisions in your code.  You can use if blocks & switch blocks, for & foreach loops and while loops too.  Despite being a language that uses curly brace and is case sensitive, it’s very easy to read and write from a syntactic angle, as demonstrated here with a foreach loop, if statement and using the Mail object:

@foreach (var p in db.Query(“SELECT * FROM PRODUCTS”)) { … }

–and–

if (Mail.UserName.IsEmpty() || Mail.Password.IsEmpty() || Mail.From.IsEmpty()) {

        <h2>Please set up Mail!</h2><p>Please set your Hotmail Username, Password, and From Address in OrderSuccess.cshtml to send mail</p>

}

else {

    Mail.Send(to: customerEmail, subject: “New Order”, body: body);

    <h2>Thank you for ordering!</h2>

} 

Some other notable code constructs available in Razor are Try/Catch exception handling and arrays.  I just wanted to highlight a few of the popular ones here in this blog post. You can get a lot more information on the language features in the ASP.NET Web Pages with Razor Syntax eBook.

Helpers

Razor helpers allow you to encapsulate and condense complex tasks into a single line of code.  Some baked in helpers are used for …

  • Google Analytics
  • Facebook Integration
  • Twitter Integration
  • Sending Email
  • Validation
  • There’s lots more…

You can also create your own helpers, and there’ll be more helpers brought to you by Microsoft in the future.  Helpers are a big part of the Razor API.

The Razor API

This is where’s it at, in the API.  APIs (Application Programming Interfaces) contain functionality that you can tap into and use, rather than having to build it yourself.  The Razor API includes an extensive of helpers and activities like file uploading, data collection w/HTML Forms, charting, sending email, website analytics, etc…are all in the Razor API, and most only take a single or few lines of code to use.

You can browse the online API documentation here.

There’s More!

Of course, there’s a lot more you can do with Razor syntax; listed in this post are just some of the basics and features that you can take advantage of when building small, highly functional, easy to use web sites.

Stats, data, and answers, as to why there are so few women in technology fields.

Women today represent an abysmal percentage of the population of most STEM fields (Science, Technology, Engineering, and Math), and that number is shrinking, rather than expanding. At the same time, fewer young women are entering the STEM workforce than in previous years.

Why are women leaving STEM fields?

Researchers have been gathering volumes of data as to the why there are fewer women are staying in, or entering STEM fields, and from that data we can see many issues that cover a spectrum from that need to be addressed:

  • Sexism: overt and subtle (hostile macho cultures)
  • Harassment, threats, or potential or actual violence toward women
  • Childcare
  • Financial Independence
  • Gender Stereotyping
  • Work-life balance

Considering the number of challenges, addressing the lack of women in technology is a multifaceted phenomenon with no single solution, with each matter deserving attention. The primary goals of this post will focus on demonstrating…

  1. Incidents of sexism at industry events, and online conversations, and their link to the decline of women in STEM fields.
  2. The effects sexism has on women and the STEM industries as a whole, both now and in the future.
  3. A call to action to drive awareness and take a proactive stance in promoting women friendly STEM workplaces, conferences, schools, and meeting places.

By understanding these influences women in technology, particularly in software development, we can take corrective and proactive stances, in the retention, engagement, and attraction of top female talent.

Incidents of sexism are major contributors to a declining female STEM workforce.

The National Center for Women In Technology describes sexist incidents [.pdf] in various ways including,

“experienced/observed exclusionary cliques, unwanted sexual teasing, being bullied, and homophobic jokes”.

Consider that  between January and October 2011, women reported 20 sexist incidents to the Geek Feminism Wiki, with some common themes: 

  • Several talks at tech conferences contained pornographic style imagery, or sexual imagery.
  • Multiple presentations referenced women in a derogatory or demeaning way, (e.g., “women can’t program”, “women are stupid”) or by overt or subtle objectification of women.
  • Overt harassment, inappropriate touching, and groping are still commonplace at technical conferences.

Roughly one incident every two weeks this year means that this happens more than we’d like to think – and that’s only the reports from a single website.

Exclusionary, offensive, incidents at conferences, along with threats, violence, and harassment, against women in technology (and women in general) are simply not isolated occasions. They have profound implications that directly impact the declining numbers of women in technology. The Washington Post outlines some statistics demonstrating this, in a study on interactions between men and women during online chat sessions.

“A 2006 University of Maryland study on chat rooms found that female participants received 25 times as many sexually explicit and malicious messages as males. A 2005 study by the Pew Internet & American Life Project found that the proportion of Internet users who took part in chats and discussion groups plunged from 28 percent in 2000 to 17 percent in 2005, entirely because of the exodus of women.” [emphasis mine]

Those numbers have barely improved, five years later. Additionally, the participants in this study belong to a general online audience and not solely the STEM fields, so one must consider the fact that STEM fields are male dominated, resulting in a larger amount of sexist behavior.

Though not the only reason, the numbers show that in software development specifically, sexist and overtly offensive behavior (both online and off) is one of two key factors as to why women are leaving technical fields as reported by ABC News. This article quotes Laura Sherbin, director at the Center for Work-Life Policy, who published a study in the Harvard Business Review titled “Reversing the Brain Drain in Science, Engineering, and Technology”. Laura goes on to explain the primary reasons women leave STEM fields…

“The top two reasons why women leave are the hostile macho cultures — the hard hat culture of engineering, the geek culture of technology or the lab culture of science … and extreme work pressures”

Sherbin also highlights just how critical and surprising the numbers are, even to researchers.

“The dropping out was a surprise to us. We knew anecdotally that women were leaving these careers. We didn’t expect to see the number 52 percent.”

To reiterate: 52% or just over half, of the female STEM workforce leaves because of hostile macho cultures.

Let’s do the math:

  • Assume the average tech conference has 300 attendees.
  • The average turnout of females at a technical conference is at about 15%, or 45 women in this example.
  • 52%, or 23 of the women at that event will leave the industry[1].
  • At a rate approximately of 26 events per year affecting 23 women each time, 598 women will be subjected to a hostile environment each year[1].

The cost in human terms and individual well-being is immeasurable.

A look at the negative effects and human cost of sexist behavior in STEM fields.

Considering the above numbers, try out this thought exercise, showing the implications of sexist incidents on women in software.

  1. Think of the names 23 women developers that you work alongside, have worked with, or know. Try it without looking at social networks, checking address books, etc…
  2. Think about these women. Are they your coworkers? Presenters you admire? Are they women with whom you enjoy having technical conversations, perhaps at conferences, code camps, or over social networks?
  3. There’s essentially a 50/50 chance, or the same chance as the toss of a coin, that those 23 women won’t be developers for much longer.

Once they’re gone, can you name 23 more women to replace them? It won’t be the younger girls entering the field.

The consequences have a stifling effect on younger girls wanting to enter the technology fields before they have a chance to start. Numbers show that a huge impasse in attracting young girls into the STEM fields, is a serious lack of women role models in those fields. Less women staying in the field means fewer role models for young girls, which in turn means fewer STEM girls overall.

It’s not just about sexist incidents though, subtle sexism can bleed into the everyday atmosphere of in tech fields and cause the same amount of negative barriers. While the day to day activ
ities of most technical women might not vary much from that of men, as far as actual programming, sitting in meetings, mundane business tasks, etc… What do differ are the interactions between the sexes, as well as both overt and subconscious behavior that manifests as sexist incidents, though primarily non-malicious, and most often subconscious. For example, here are some commonplace scenarios where subtle sexism happens in companies large and small[2][3]:

  • Men who repeatedly ask only the women attending meeting to take notes, or get coffee, when the woman is not a secretary or in a similar role.
  • Colleagues that routinely ignore women during meetings, or a female states an idea that is promptly ignored, then raised again by a man who gets the credit. (in a consistent, frequent, pattern)
  • Women, rather than men, are routinely stuck into “softer” positions, often to answer phones. Management gives women more remedial tasks that are clearly not aligned with their job description or what they were hired to do.

The sentiments above are detailed in a report by Level Playing Field Institute titled “The Tilted Playing Field: Hidden bias in information technology workspaces”  [.pdf]. Reading about recent events and stories of everything from demeaning comments, to outright harassment, stalking, and groping, are still commonplace in the tech industry. I must agree that I’ve personally been privy to a number of these types of scenarios, but that’s not all…

When an incident at a conference happens, I inevitably get a call or email from a female colleague who has just given up, and is now looking at non-technical career alternatives.

If we are to keep our technical industries healthy, and full of diverse creativity, things must change, and soon. So what can you do?

A Call to Action: Drive awareness and take the lead to promote diversity in STEM fields.

Below are just some of the things you can do to drive diversity and promote women in STEM fields:

Drive awareness.

It may seem obvious, but without awareness, it’s impossible to know there’s a problem.

You can drive awareness by blogging, tweeting, or otherwise telling your story, or commenting on blogs to show your support. The Level Playing field’s report shows a real lack of awareness in populations at large. The more blog posts, articles, and events, mean more information people can use to take proactive stances to create technical communities and workspaces that are welcoming to everyone.

Be proactive.

  • Does your company have a diversity and inclusion policy? Even if you work for a small business or startup, a formal policy of inclusion fosters a welcoming environment for everyone. If you company doesn’t have one, get involved and ask your HR department to work on one with you. Don’t let your policy be a paper form of lip service, make it part of how you do business.
  • Does your HR department have a clear open door policy, with a trusted employee to listen to concerns?
  • Attend women in technology events. Hint: Take your favorite gal developer with you. At the Code Camp NYC 2011 WIT luncheon, a healthy mix of men and women joined in for a productive, round-table discussion.
  • Ask technical women work on a joint talk with you for a user group or code camp, and invite them to technical events.

Awesome guys like John Zablocki and coworkers like Joe Healy, Peter Laudati, and Brian Prince, are just a few of the many guys I see at WIT related events.

Presenters & conference organizers:

Speakers can use the Windows Phone 7 app content guidelines, or the Android app marketplace rating guide when s/he’s not sure what material should be considered offensive.

Organizers can create written guidelines to ensure a harassment-free environment for everyone at your conference, user group, or other meeting.

CodeStock 2010 set a perfect example to follow by embracing a WIT centered theme, including a female keynote speaker (*ahem* that would be me 🙂 ).

Summary

I would love to see every company behave as MS DPE East does, and I hope that you, dear readers of this blog, will step up to foster an environment in your workplaces and homes that support and celebrate women and diversity in STEM fields.

Should an incident occur at an event you’re attending, take corrective action as soon as possible. If you’re in a conference session and you feel offended or uncomfortable, walk out calmly, and write down exactly what you feel is offensive or inappropriate. Take the evaluation to the conference staff, and ask that they check out the session in question.

[1] The numbers in this sample represent one source of reports, so the actual numbers are much higher. Additionally, the number 23 is rounded from 23.4. Also assuming a single track conference, which is fairly common.

[2] These aren’t just manufactured scenarios – they’re real life stories from female contemporaries.

[3] As for large companies, my experiences at Microsoft DPE have been great!. I work on an highly functioning team with awesome people who celebrate diversity in technology and are quite supportive of each other.

Add HTML5 Geolocation plus Bing Maps into ASP.NET MVC views

The Bing Maps API is a free, easy to use API, that allows you to incorporate mapping features into your ASP.NET MVC or application by using Web standards such as JavaScript, and the now supported HTML5 Geolocation.

Bing Maps and ASP.NET MVC

A Bing maps API key is required when using the API. The Bing Maps key allows you to access Geolocation data, and to manipulate an in-view Map object with JavaScript via the Bing Maps API. The Bing Maps Developer Portal is where you can get a key by registering with your Windows Live ID.

Once you’re set with a key, you’ll need these files in your MVC project to develop with Bing Maps:

ScriptsYourBingMapsScript.js – This file contains your script that works with Bing Maps & Geolocation.

ContentSite.css – A small bit of CSS is required to style the Map

ViewsBingMapsIndex.cshtml – The MVC view that contains the Bing Map HTML

Since the code is HTML &CSS that conform to Web standards, the bulk of the lives is in the .js file and/or the view. Although using MVC, the model and controller are not necessary for manipulating maps with client side script, but don’t throw out the model and controller yet, as you will need them to work with other data.

The Bing Maps Interactive SDK

If you’re writing code that uses Bing Maps, the Interactive Bing Maps SDK is a “must visit” Web site. By choosing the options on the left of the page, the Bing Maps Interactive SDK creates usable JavaScript, and a “View HTML ” button that exposes the page source.

 

image_2

The Bing Maps API & SDK contain more than an interactive website. Bing Maps development gives you access to many productive development tools such as:

  • The Bing Maps AJAX Control (multiple versions)
  • The Bing Maps iOS Control
  • A Bing Maps Silverlight Control
  • SOAP and REST services
  • More…

You can use the Bing Maps Interactive API to create the equivalent code as the samples shown in this post.

Render Bing Maps in MVC views with the Bing Maps AJAX control.

While it’s called the Bing Maps AJAX control, it’s not a control at all, but a JavaScript library instead. HTML and client side script (JavaScript, jQuery, etc…) are the enabling technologies for Bing Maps on the ASP.NET (or any Web) platform. To reference the Bing Maps AJAX Control, your view needs the <script> reference below.

<script src="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=7.0" type="text/javascript"></script>

If you plan to use the Bing Maps AJAX control in multiple views, the <script> reference can go in the _Layout.cshtml file, otherwise you can add it to the required views or a different layout page. Inside a view, a <div> element should contain and display the map, and is also the DOM object that you manipulate in code, so it needs an id attribute.

<div id="map"></div>
Since the browser renders a tiny <div> by default, some CSS is necessary, such as the position, width, and height, in which to create a suitable DOM shape for maps. You can save the CSS in the ContentSite.css file, or its own file, for reusability across views.  
<style>
#map
{
    position:relative; 
    width: 500px; 
    height: 500px; 
    border:0px
}
</style>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

After the HTML is in place, you can write code to capture the user's positional data to display a Bing map showing the location, nearby restaurants, or other information requested by the user. 

Display a Bing Map with a Pushpin.

You first need positional data from the user before displaying the map. Once you have the positional data points, i.e., latitude and longitude, you can add a Bing Map to any MVC view. To learn how to obtain positional data for your Web site or app, see this post on creating location aware Web sites with the HTML5 Geolocation.

The code below retrieves the latitude and longitude coordinates from the position argument of a showMap method, then creates an instance of a Map object the position, credentials, center, map type, and zoom level. The code continues on by centering the Pushpin to represent the user’s location in the map.

function showMap(position) {
 
    var latitude = position.coords.latitude;
    var longitude = position.coords.longitude;
 
    var map = new Microsoft.Maps.Map($("#map")[0],
    { 
        credentials: "Your Bing Maps API Key",
        center: new Microsoft.Maps.Location(latitude, longitude),
        mapTypeId:   Microsoft.Maps.MapTypeId.road,
        zoom:        10
    });   
 
    var center = map.getCenter();
    var pin = new Microsoft.Maps.Pushpin(center, { width: 50, height: 50, draggable: false });
    map.entities.push(pin);
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

The result should look something like this (but with your coordinates):

SNAGHTML1015b426

Should you want to customize the Pushpin icon, just change the Pushpin construction arguments, and pass in the path and name of the graphics file (.png, .jpg., and standard Web formats).

var pin = new Microsoft.Maps.Pushpin(center, {icon: 'CustomPushpin.png', width: 50, height: 50, draggable: true}); 

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Customizing the map further by adding an Infobox, which is a small rectangle with information about a particular location, takes only a few lines of code. Make sure the clear method is run before pushing an Infobox onto a map or the latest Infobox, Pushpin, or other object will overlay the previous.

 map.entities.clear(); 
 var infoboxOptions = {title:'Bing Maps Rock!', description:'Add an Infobox to a map with very little JavaScript!'}; 
 var defaultInfobox = new Microsoft.Maps.Infobox(map.getCenter(), infoboxOptions );    
 map.entities.push(defaultInfobox);

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

The above code creates an Infobox on the map similar to the one shown here:

SNAGHTML101866d1 

These are just a few simple, but core examples, of what you can do with Bing Maps. For more information on developing for Bing Maps, see below in the Summary & Resources.

Summary & Resources

The Bing Maps AJAX control is a handy library you can use to add geo-interactivity to your Web sites with little code. Additionally, you can incorporate other APIs to make full featured location aware mapping apps.

Use the W3C Geolocation API to create location aware Web sites

The Bings Map control (Bing Maps API)

Bing Maps Articles

Customizing Bing Maps Pushpins

G. Andrew Duthie demonstrates bing maps in action with CommunityMegaphone.com

ASP.NET MVC ActionResults explained

Action results are an important part of the ASP.NET MVC controller system, and definitely worth taking a good look at. Understanding how they work gives you many more choices in MVC and that will certainly help make your code better.

What is an ActionResult?

An ActionResult is a return type of a controller method, also called an action method, and serves as the base class for *Result classes. Action methods return models to views, file streams, redirect to other controllers, or whatever is necessary for the task at hand. The controller takes on this responsibility to connect system components, acting as a traffic cop.

There are many derived ActionResult types you can use to return results that are more specific for a particular view. You can quickly access the derived types of the ActionResult during development by hovering over an ActionResult in an action result’s method signature then expanding the type tool window, to see what *Results the ASP.NET Framework provides.To get a deeper look at what exactly an ActionResult type is and how it works, running the code with a breakpoint set at the end of an action result method will get the information we want. Inspecting the image below of the Watch window shows some of the properties that you can tap into that ActionResults return.

Notice the Model, TempData, ViewBag, and ViewData properties. Drilling into the Watch window even further exposes the Model property’s strongly typed collection of objects.

SNAGHTML4d9b785_thumb3_2

These objects contain everything you need when working in the view. Of course, the Model is the most heavily used object, containing our application’s schema and data. The TempData object holds data between multiple controllers, while ViewBag and ViewData objects holds data between controllers and/or views.

Since the Model property is the actual model the view uses to render the data, its data type should align with the type specified in the @model directive in the target view. As pointed out in the image above, the Model property contains a strongly typed list of Product objects (or whatever you’re returning), matching the view’s model.

Looking in the Watch window shows that the runtime converts the ActionResult to a ViewResult, however you’ll want to be more specific during design time. Swapping ActionResults for more specific/derived classes, for example, a ViewResult, produce the exact same object structure as the ActionResult. With this in mind, using more specific types increases code accuracy, maintainability, and even performance as the compiler has a much better idea of what should happen at compile time, rather than at the last minute at runtime, since no runtime conversion happens.

Action methods, action results & routing

Action methods and the routing system work together in every MVC application. MVC does this by using a set of conventions, defined as routing patterns in the global.asax.cs file. These patterns connect HTTP requests with controllers and action methods. As an HTTP Request enters the routing system, it determines which controller should serve data to which view (if any).

The global.asax.cs defines the default routing pattern, {controller}/{action}/{id}, as described in more detail here:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
    );
}

Picking apart each piece of the route pattern is a great way to digest what the routing system is doing…

  • {controller} Controller maps a part of the URL to the name of the controller class. For example, a class named ProductsController, will map to URLs that start with /Products (after the domain of course). ASP.NET automatically drops the word “Controller” from the URL so is it’s more user friendly, e.g., /Products vs. /ProductsController.
  • {action} Action maps a part of the URL to the individual methods inside controllers. Therefore the ProductsController.Edit(…) and ProductsController.Details(…) methods align with the /Products/Edit and Products/Details URLs, respectively. Action maps without any parameters, since the next route pattern, id, defines them.
  • {id} Id maps to an identifier, such as a product id or a product name. These are controller action method parameters, so the value at the end of the URL is generally the value of the method’s argument. For example, /Products/Edit/2 matches up with the id argument in ProductsController.Edit(int id). The controller methods normally use this id to query for a single record with a matching id to return to the view.

Below is a table detailing the mappings between routes, controllers, action methods and their parameters.

Action Method Route {controller}/{action}/{id} HTTP POST/GET
public ActionResult Index() { } /Products GET
public ActionResult Details(int id) { } /Products/Details/id GET, values in URL
public ActionResult Edit(int id) { } /Products/Edit/id GET, values in URL
[HttpPost]
public ActionResult Edit(int id, FormCollection collection) { }
/Products/Edit/id POST, values in FormCollection
public ActionResult Create() { } /Products/Create GET
[HttpPost]
public ActionResult Create(FormCollection collection) { }
/Products/Create POST, values in FormCollection
public ActionResult Delete(int id) { } /Products/Delete/id GET, values in URL
[HttpPost]
public ActionResult Delete(int d, FormCollection collection) { }
/Products/Delete/id POST, values in FormCollection

You may have noticed that the Edit, Create, and Delete action methods come overloaded as pairs, and an [HttpPost] attribute decorates one method in each pair. Since [HttpGet] is the default, the other method doesn’t need to be marked. Additionally, all methods decorated with the [HttpPost] attribute are meant to accept HTML input fields located between the <form> tags. The collection parameter of type FormCollection[1] contains all the input fields from the <form> of the HTTP Post.

Every method in a controller class returns an ActionResult by default; however, some actions will be more optimized, clear, or accurate in the code, if we are to specify a more specific action results, for instance, a ViewResult, rather than an ActionResult. Action result methods can also designate that its result will return something other than data for a view, e.g., a HttpNotFoundResult or an HttpStatusCodeResult, as shown in the code below:

Returns an HTTP 404 Not found error:

public HttpStatusCodeResult NotFound()
{
    var result = new HttpStatusCodeResult(404);
    return result;
}

Redirects to a separate view altogether:

[HttpPost]
public RedirectResult Create(FormCollection collection)
{
    // code to save form data ...     
    return new RedirectResult("Home/Index", false);
}

There’s many more ActionResult types to explore. Check them out and find something that meets the needs of your controller and/or view.

Summary

ActionResults are a key component to ASP.NET MVC, so understanding them is essential for MVC application development. Whether you need to make AJAX calls, redirect, return a file stream, or just return data to a view, ActionResults are right there in the center of all the……action.

[1] I recommend rather than using FormCollection, you should use a strongly typed parameter or multiple, differently typed parameters that match to data types in the HTML form. Look forward to a blog post soon to demonstrate this.

Building a relational data model in ASP.NET MVC w/EF Code First

Just about every application uses some sort of data model, and .NET developers have been using POCOs (Plain Old CLR Objects) for some time now. You can use either new or existing POCOs in MVC 3 applications and still take advantage of EF (Entity Framework), and in particular, EF’s Code First feature. EF’s Code First feature allows you to base both an application and a database from your data model. EF additionally carries features for database and model first development.

Data Models, ORMs & Entity Framework

As with most business apps of any type, data models are at the heart of an application. When developing ASP.NET MVC applications it’s best to go with an ORM (Object-Relational Mapper) such as EF, as ORMs alleviate many pains in dealing with databases and their objects. Since MVC is extensible and pluggable, you also have the choice of using 3rd party or open source ORMs, for example, the widely used nHibernate.

That’s where things can get complex, and that’s where EF fits in with multiple strategies to help alleviate common pains in modeling. There are many ways you can model data to represent and manipulate it the way you need to, either visually with a designer, or by using code. EF supports these data access options:

  • Database first
    • You can use Visual Studio to connect to a data source and visually generate a data model from an existing database(s).
  • Model first
    • Using model first you can build brand new databases from models you’ve created using the designers in Visual Studio.
  • Code First
    • With code first, you start with your own POCOs, just add a small amount of code, and voilà, instant ORM.

In addition to these features, EF has more advanced features, such as a XML based schema mappings and fluent APIs. EF is flexible enough to cover the spectrum of applications from the smallest of web sites to enterprise applications.

Before coding EF classes, you must add a NuGet package reference to EntityFramework by selecting “Add Library Package Reference” from the Project menu, and before using SQL CE 4.0 you’ll need to add a regular reference to the System.Data.SqlServerCe library.

Building the basic data model

Code First is a feature of EF that maps POCOs containing classes, relationships, data annotations, etc…, to database tables, columns, constraints, and relationships in physical databases. EF CF creates the database by examining the code in the data model, then building the corresponding physical database and its objects. You have the option to merge or drop/recreate any databases generated by EF Code First, and you can additionally seed the database with  data (coming in a later post).

Since the controller returns the model to the view, you can send validation information to the view by using Data Annotations. Data annotations are attributes that you can apply to a model to perform common types of validation at the property level, as shown below in two basic POCO classes.

public class Category

{

    public int Id { get; set; }

 

    [DisplayName("Category")]

    [Required(ErrorMessage = "The product category is required.")]

    public string Name { get; set; }

}

public class Product

{

    public int Id { get; set; }

 

    [DisplayName("Delicious Treat")]

    [Required(ErrorMessage = "The product name field is required.")]

    public string Name { get; set; }

 

    [Required(ErrorMessage = "The product description field is required.")]

    public string Description { get; set; }

 

    [DisplayName("Sale Price")]

    [Required(ErrorMessage = "The Sale Price field is required.")]

    public decimal Price { get; set; }

 

    [DisplayName("Made fresh on")]

    [Required(ErrorMessage = "The Freshly Baked On field is required.")]

    public DateTime CreationDate { get; set; }

 

    [DisplayName("Don't Sell After")]

    [Required(ErrorMessage = "The Expiration Date field is required.")]

    public DateTime ExpirationDate { get; set; }

 

    [DisplayName("Qty Available")]

    [Required(ErrorMessage = "The Qty Available field is required.")]

    [Range(0, 120,ErrorMessage="The Qty Available must be between 0 and 120.")]

    public int QtyOnHand { get; set; }

 

    [DisplayName("Product Image")]

    public string ImageName { get; set; }

}

Now that you have a model, you can add a few lines of code to tell EF to generate the database for you, and even seed it with data if you want to. In order for EF to know what classes in a project it should use as a model to generate the database, you need to tap into two classes from the System.Data.Entity namespace:

  • DBContext class.
    • The DbContext is a lot like a connection, except it manages database connectivity for you automatically (i.e., no need to explicitly call open/close on connections). Additionally, there are many properties methods on the DbContext class to work directly with the model and/or database, such as the SaveChanges method or the ValidateEntity method.
  • DbSet class
    • This object knows how to deal with CRUD operations on the entity class itself (i.e., Category or Product), and works in tandem with the DbContext object to perform those operations.

A data model is not just a set of POCO classes, though. Models need a class to manage the POCOs, perform connection management, or other duties that an ORM would do. These management classes are often called a context or repository[1]. Rather than writing the database and connection management code yourself, you can take advantage of EF and receive features provided automatically by inheriting from the DbContext class in your repository class.

The DbContext also needs to know what POCO collections to work with. You can do this by adding properties of type DbSet<T> for each of your collection types, as the code below demonstrates.

public class FourthCoffeeWebContext : DbContext

{

    public DbSet<Category> Categories { get; set; }

    public DbSet<Product> Products { get; set; }

}

At this point, the two POCO classes and DbContext are all you need to see EF in action, and you can move onto running the application and generating the physical database.

Generating the database from the model

Assuming you have the controllers and views in place to perform CRUD operations on the Categories and Products collections, running the MVC application will create a SQL (Express or CE 4.0) database automatically for you. Of course, there’s no data, just the schema, but the site and database are both up, running, and completely functional. Navigating to the create action on the products controller in a browser renders the create view like the one below (including validation!):

 

image_6

 

Once you save a product, the app takes you back to the listing of products, where you can see the results.

image_8

Although you can see the data on in the browser, you probably can’t find the database in the Solution Explorer. Checking out the customary App_Data folder reveals nothing, and examining the Web.Config file comes up empty. Since EF could find no information about the database, it created a SQL Express[2] database with the a default name and path shown here:

C:Program FilesMicrosoft SQL ServerMSSQL10_50.SQLEXPRESSMSSQLDATAFourthCoffee.Web.Models.FourthCoffeeWebContext.mdf.

If you want to name your database something different, modify the <connectionStrings> section of the Web.Config file to point to the preferred database name and location. This connection string connects to the App_Databakery.sdf database.

<connectionStrings>  

  <add name="FourthCoffeeWebContext" connectionString="Data Source=|DataDirectory|bakery.sdf" 

  providerName="System.Data.SqlServerCe.4.0" />

</connectionStrings>

By convention, the name of this connection string needs to match the name of your context/repository class, in this case, FourthCoffeeWebContext, so EF can identify the connection string to use. Notice that the connection string points to the data directory (App_Data) and it’s a SQL CE 4.0 database. If you wish to use a different edition of SQL, feel free to change the connection string and provider name to point to other locations.

Once the changes are in place, run the application, enter some data, and return to Visual Studio where you can see the App_Data folder now contains the bakery.sdf database.

image_10

Since the option to drop and recreate the database exists, you can design your data model through code and tests to verify that it works in a repetitive cycle, so relating the classes and regenerating the database is easy.

Relating classes in the data model

The Category and Product classes relate to each other in a one-(zero or)many relationship. You can express this relationship in code by adding a property in the Category class to represent the collection of related products, as shown here:

public virtual ICollection<Product> Products { get; set; }

The Product class needs two lines of code, so you’ll need to add the following properties below to the Product class.

public int CategoryId { get; set; }

public virtual Category Category { get; set; }

While the data model is complete, the code in controllers and views does not reflect the updates made to the model. The Edit and Create views associated with the Product need to include a dropdown of the categories, with the current product’s category selected, similar to the code below:

class="editor-label">

    Category

class="editor-field">

    @Html.DropDownListFor(model => model.CategoryId, 

    ((IEnumerable)ViewBag.PossibleCategories)

        .Select(option => new SelectListItem {

        Text = (option == null ? "None" : option.Name), 

        Value = option.Id.ToString(),

        Selected = (Model != null) && (option.Id == Model.CategoryId)

    }), "Choose...")

    @Html.ValidationMessageFor(model => model.CategoryId)