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.

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)