ASP.NET MVC part 6 Examining the Edit Methods and Edit View

Examining the Edit Methods and Edit View

In this section, you’ll examine the generated action methods and views for the movie controller. Then you’ll add a custom search page.

Run the application and browse to the Movies controller by appending /Movies to the URL in the address bar of your browser. Hold the mouse pointer over an Edit link to see the URL that it links to.

EditLink_sm

The Edit link was generated by the Html.ActionLink method in the Views\Movies\Index.cshtml view:

 @Html.ActionLink("Edit", "Edit", new { id=item.ID })

Html.ActionLink

The Html object is a helper that’s exposed using a property on the WebViewPage base class. The ActionLinkmethod of the helper makes it easy to dynamically generate HTML hyperlinks that link to action methods on controllers. The first argument to the ActionLink method is the link text to render (for example, <a>Edit Me</a>). The second argument is the name of the action method to invoke. The final argument is ananonymous object that generates the route data (in this case, the ID of 4).

The generated link shown in the previous image is http://localhost:xxxxx/Movies/Edit/4. The default route takes the URL pattern {controller}/{action}/{id}. Therefore, ASP.NET translateshttp://localhost:xxxxx/Movies/Edit/4 into a request to the Edit action method of the Movies controller with the parameter ID equal to 4.

You can also pass action method parameters using a query string. For example, the URLhttp://localhost:xxxxx/Movies/Edit?ID=4 also passes the parameter ID of 4 to the Edit action method of theMovies controller.

EditQueryString

Open the Movies controller. The two Edit action methods are shown below.

//
// GET: /Movies/Edit/5

public ActionResult Edit(int id) 
{
    Movie movie = db.Movies.Find(id);
    return View(movie);
}

//
// POST: /Movies/Edit/5

[HttpPost]
public ActionResult Edit(Movie movie) 
{
    if (ModelState.IsValid) 
    {
        db.Entry(movie).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(movie);
}

Notice the second Edit action method is preceded by the HttpPost attribute. This attribute specifies that that overload of the Edit method can be invoked only for POST requests. You could apply the HttpGet attribute to the first edit method, but that’s not necessary because it’s the default. (We’ll refer to action methods that are implicitly assigned the HttpGet attribute as HttpGet methods.)

The HttpGet Edit method takes the movie ID parameter, looks up the movie using the Entity Framework Findmethod, and returns the selected movie to the Edit view. When the scaffolding system created the Edit view, it examined the Movie class and created code to render <label> and <input> elements for each property of the class. The following example shows the Edit view that was generated:

@model MvcMovie.Models.Movie

@{
    ViewBag.Title = "Edit";
}

<h2>Edit</h2>

<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

@using (Html.BeginForm()) {
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>Movie</legend>

        @Html.HiddenFor(model => model.ID)

        <div class="editor-label">
            @Html.LabelFor(model => model.Title)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Title)
            @Html.ValidationMessageFor(model => model.Title)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.ReleaseDate)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.ReleaseDate)
            @Html.ValidationMessageFor(model => model.ReleaseDate)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Genre)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Genre)
            @Html.ValidationMessageFor(model => model.Genre)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Price)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Price)
            @Html.ValidationMessageFor(model => model.Price)
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

Notice how the view template has a @model MvcMovie.Models.Movie statement at the top of the file — this specifies that the view expects the model for the view template to be of type Movie.

The scaffolded code uses several helper methods to streamline the HTML markup. The Html.LabelFor helper displays the name of the field (“Title”, “ReleaseDate”, “Genre”, or “Price”). The Html.EditorFor helper displays an HTML <input> element. The Html.ValidationMessageFor helper displays any validation messages associated with that property.

Run the application and navigate to the /Movies URL. Click an Edit link. In the browser, view the source for the page. The HTML in the page looks like the following example. (The menu markup was excluded for clarity.)

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>Edit</title>
    <link href="/Content/Site.css" rel="stylesheet" type="text/css" />
    <script src="/Scripts/jquery-1.5.1.min.js" type="text/javascript"></script>
    <script src="/Scripts/modernizr-1.7.min.js" type="text/javascript"></script>
</head>
<body>
    <div class="page">
        <header>
            <div id="title">
                <h1>MVC Movie App</h1>
            </div>
           ...
        </header>
        <section id="main">
            

<h2>Edit</h2>

<script src="/Scripts/jquery.validate.min.js" type="text/javascript"></script>
<script src="/Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>

<form action="/Movies/Edit/4" method="post">    <fieldset>
        <legend>Movie</legend>

        <input data-val="true" data-val-number="The field ID must be a number." 
                data-val-required="The ID field is required." id="ID" name="ID" type="hidden" value="4" />

        <div class="editor-label">
            <label for="Title">Title</label>
        </div>
        <div class="editor-field">
            <input class="text-box single-line" id="Title" name="Title" type="text" value="Rio Bravo" />
            <span class="field-validation-valid" data-valmsg-for="Title" data-valmsg-replace="true"></span>
        </div>

        <div class="editor-label">
            <label for="ReleaseDate">ReleaseDate</label>
        </div>
        <div class="editor-field">
            <input class="text-box single-line" data-val="true" data-val-required="The ReleaseDate field is required." 
                id="ReleaseDate" name="ReleaseDate" type="text" value="4/15/1959 12:00:00 AM" />
            <span class="field-validation-valid" data-valmsg-for="ReleaseDate" data-valmsg-replace="true"></span>
        </div>

        <div class="editor-label">
            <label for="Genre">Genre</label>
        </div>
        <div class="editor-field">
            <input class="text-box single-line" id="Genre" name="Genre" type="text" value="Western" />
            <span class="field-validation-valid" data-valmsg-for="Genre" data-valmsg-replace="true"></span>
        </div>

        <div class="editor-label">
            <label for="Price">Price</label>
        </div>
        <div class="editor-field">
            <input class="text-box single-line" data-val="true" data-val-number="The field Price must be a number." 
                data-val-required="The Price field is required." id="Price" name="Price" type="text" value="9.99" />
            <span class="field-validation-valid" data-valmsg-for="Price" data-valmsg-replace="true"></span>
        </div>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>
</form>
<div>
    <a href="/Movies">Back to List</a>
</div>

        </section>
        <footer>
        </footer>
    </div>
</body>
</html>

The <input> elements are in an HTML <form> element whose action attribute is set to post to the /Movies/EditURL. The form data will be posted to the server when the Edit button is clicked.

Processing the POST Request

The following listing shows the HttpPost version of the Edit action method.

[HttpPost]
public ActionResult Edit(Movie movie) 
{
    if (ModelState.IsValid) 
    {
        db.Entry(movie).State = EntityState.Modified;
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    return View(movie);
}

The ASP.NET framework model binder takes the posted form values and creates a Movie object that’s passed as the movie parameter. The ModelState.IsValid check in the code verifies that the data submitted in the form can be used to modify a Movie object. If the data is valid, the code saves the movie data to the Moviescollection of the MovieDBContext instance. The code then saves the new movie data to the database by calling the SaveChanges method of MovieDBContext, which persists changes to the database. After saving the data, the code redirects the user to the Index action method of the MoviesController class, which causes the updated movie to be displayed in the listing of movies.

If the posted values aren’t valid, they are redisplayed in the form. The Html.ValidationMessageFor helpers in the Edit.cshtml view template take care of displaying appropriate error messages.

abcNotValid

Note about locales   If you normally work with a locale other than English, see Supporting ASP.NET MVC 3 Validation with Non-English Locales.

Making the Edit Method More Robust

The HttpGet Edit method generated by the scaffolding system doesn’t check that the ID that’s passed to it is valid. If a user removes the ID segment from the URL (http://localhost:xxxxx/Movies/Edit), the following error is displayed:

Null_ID

A user could also pass an ID that doesn’t exist in the database, such ashttp://localhost:xxxxx/Movies/Edit/1234. You can make two changes to the HttpGet Edit action method to address this limitation. First, change the ID parameter to have a default value of zero when an ID isn’t explicitly passed. You can also check that the Find method actually found a movie before returning the movie object to the view template. The updated Edit method is shown below.

public ActionResult Edit(int id = 0)
{
    Movie movie = db.Movies.Find(id);
    if (movie == null)
    {
        return HttpNotFound();
    }
    return View(movie);
}

If no movie is found, the HttpNotFound method is called.

All the HttpGet methods follow a similar pattern. They get a movie object (or list of objects, in the case ofIndex), and pass the model to the view. The Create method passes an empty movie object to the Create view. All the methods that create, edit, delete, or otherwise modify data do so in the HttpPost overload of the method. Modifying data in an HTTP GET method is a security risk, as described in the blog post entry ASP.NET MVC Tip #46 – Don’t use Delete Links because they create Security Holes. Modifying data in a GET method also violates HTTP best practices and the architectural REST pattern, which specifies that GET requests should not change the state of your application. In other words, performing a GET operation should be a safe operation that has no side effects.

Adding a Search Method and Search View

In this section you’ll add a SearchIndex action method that lets you search movies by genre or name. This will be available using the /Movies/SearchIndex URL. The request will display an HTML form that contains input elements that a user can fill in in order to search for a movie. When a user submits the form, the action method will get the search values posted by the user and use the values to search the database.

SearchIndx_SM

Displaying the SearchIndex Form

Start by adding a SearchIndex action method to the existing MoviesController class. The method will return a view that contains an HTML form. Here’s the code:

public ActionResult SearchIndex(string searchString)
{          
    var movies = from m in db.Movies
                 select m;

    if (!String.IsNullOrEmpty(searchString))
    {
        movies = movies.Where(s => s.Title.Contains(searchString));
    }

    return View(movies);
}

The first line of the SearchIndex method creates the following LINQ query to select the movies:

var movies = from m in db.Movies
                 select m;

The query is defined at this point, but hasn’t yet been run against the data store.

If the searchString parameter contains a string, the movies query is modified to filter on the value of the search string, using the following code:

if (!String.IsNullOrEmpty(searchString))
    {
        movies = movies.Where(s => s.Title.Contains(searchString));
    }

LINQ queries are not executed when they are defined or when they are modified by calling a method such asWhere or OrderBy. Instead, query execution is deferred, which means that the evaluation of an expression is delayed until its realized value is actually iterated over or the ToList method is called. In the SearchIndexsample, the query is executed in the SearchIndex view. For more information about deferred query execution, see Query Execution.

Now you can implement the SearchIndex view that will display the form to the user. Right-click inside theSearchIndex method and then click Add View. In the Add View dialog box, specify that you’re going to pass aMovie object to the view template as its model class. In the Scaffold template list, choose List, then clickAdd.

AddSearchView

When you click the Add button, the Views\Movies\SearchIndex.cshtml view template is created. Because you selected List in the Scaffold template list, Visual Web Developer automatically generated (scaffolded) some default content in the view. The scaffolding created an HTML form. It examined the Movie class and created code to render <label> elements for each property of the class. The listing below shows the Create view that was generated:

@model IEnumerable<MvcMovie.Models.Movie>

@{
    ViewBag.Title = "SearchIndex";
}

<h2>SearchIndex</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table>
    <tr>
        <th>
            Title
        </th>
        <th>
            ReleaseDate
        </th>
        <th>
            Genre
        </th>
        <th>
            Price
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Title)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ReleaseDate)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Genre)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Price)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
            @Html.ActionLink("Details", "Details", new { id=item.ID }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.ID })
        </td>
    </tr>
}

</table>

Run the application and navigate to /Movies/SearchIndex. Append a query string such as ?searchString=ghost to the URL. The filtered movies are displayed.

SearchQryStr

If you change the signature of the SearchIndex method to have a parameter named id, the id parameter will match the {id} placeholder for the default routes set in the Global.asax file.

{controller}/{action}/{id}

The modified SearchIndex method would look as follows:

public ActionResult SearchIndex(string id)
{
    string searchString = id;
    var movies = from m in db.Movies
                 select m;

    if (!String.IsNullOrEmpty(searchString))
    {
        movies = movies.Where(s => s.Title.Contains(searchString));
    }

    return View(movies);
}

You can now pass the search title as route data (a URL segment) instead of as a query string value.

SearchRouteData

However, you can’t expect users to modify the URL every time they want to search for a movie. So now you you’ll add UI to help them filter movies. If you changed the signature of the SearchIndex method to test how to pass the route-bound ID parameter, change it back so that your SearchIndex method takes a string parameter named searchString:

public ActionResult SearchIndex(string searchString)
{          
     var movies = from m in db.Movies
                  select m;

    if (!String.IsNullOrEmpty(searchString))
    {
        movies = movies.Where(s => s.Title.Contains(searchString));
    }

    return View(movies);
}

Open the Views\Movies\SearchIndex.cshtml file, and just after @Html.ActionLink("Create New", "Create"), add the following:

@using (Html.BeginForm()){   
         <p> Title: @Html.TextBox("SearchString") 
         <input type="submit" value="Filter" /></p>
        }

The following example shows a portion of the Views\Movies\SearchIndex.cshtml file with the added filtering markup.

@model IEnumerable<MvcMovie.Models.Movie>

@{
    ViewBag.Title = "SearchIndex";
}

<h2>SearchIndex</h2>

<p>
    @Html.ActionLink("Create New", "Create")
    
     @using (Html.BeginForm()){   
         <p> Title: @Html.TextBox("SearchString") <br />  
         <input type="submit" value="Filter" /></p>
        }
</p>

The Html.BeginForm helper creates an opening <form> tag. The Html.BeginForm helper causes the form to post to itself when the user submits the form by clicking the Filter button.

Run the application and try searching for a movie.

SearchIndxIE9_title

There’s no HttpPost overload of the SearchIndex method. You don’t need it, because the method isn’t changing the state of the application, just filtering data. If you added the following HttpPost SearchIndexmethod, the action invoker would match the HttpPost SearchIndex method, and the HttpPost SearchIndexmethod would run as shown in the image below.

[HttpPost]
public string SearchIndex(FormCollection fc, string searchString)
{
    return "<h3> From [HttpPost]SearchIndex: " + searchString + "</h3>";
}

SearchPostGhost

Adding Search by Genre

If you added the HttpPost version of the SearchIndex method, delete it now.

Next, you’ll add a feature to let users search for movies by genre. Replace the SearchIndex method with the following code:

public ActionResult SearchIndex(string movieGenre, string searchString)
{
    var GenreLst = new List<string>();

    var GenreQry = from d in db.Movies
                   orderby d.Genre
                   select d.Genre;
    GenreLst.AddRange(GenreQry.Distinct());
    ViewBag.movieGenre = new SelectList(GenreLst);

    var movies = from m in db.Movies
                 select m;

    if (!String.IsNullOrEmpty(searchString))
    {
        movies = movies.Where(s => s.Title.Contains(searchString));
    }

    if (string.IsNullOrEmpty(movieGenre))
        return View(movies);
    else
    {
        return View(movies.Where(x => x.Genre == movieGenre));
    }

}

This version of the SearchIndex method takes an additional parameter, namely movieGenre. The first few lines of code create a List object to hold movie genres from the database.

The following code is a LINQ query that retrieves all the genres from the database.

var GenreQry = from d in db.Movies
                   orderby d.Genre
                   select d.Genre;

The code uses the AddRange method of the generic List collection to add all the distinct genres to the list. (Without the Distinct modifier, duplicate genres would be added — for example, comedy would be added twice in our sample). The code then stores the list of genres in the ViewBag object.

The following code shows how to check the movieGenre parameter. If it’s not empty the code further constrains the movies query to limit the selected movies to the specified genre.

 if (string.IsNullOrEmpty(movieGenre))
        return View(movies);
    else
    {
        return View(movies.Where(x => x.Genre == movieGenre));
    }

Adding Markup to the SearchIndex View to Support Search by Genre

Add an Html.DropDownList helper to the Views\Movies\SearchIndex.cshtml file, just before the TextBoxhelper. The completed markup is shown below:

<p>
    @Html.ActionLink("Create New", "Create")
    @using (Html.BeginForm()){   
         <p>Genre: @Html.DropDownList("movieGenre", "All")  
        &nbsp;  Title: @Html.TextBox("SearchString")  
         <input type="submit" value="Filter" /></p>
        }
</p>

Run the application and browse to /Movies/SearchIndex. Try a search by genre, by movie name, and by both criteria.

In this section you examined the CRUD action methods and views generated by the framework. You created a search action method and view that let users search by movie title and genre. In the next section, you’ll look at how to add a property to the Movie model and how to add an initializer that will automatically create a test database.

ASP.NET MVC part 5 Accessing your Model’s Data from a Controller

Accessing your Model’s Data from a Controller

In this section, you’ll create a new MoviesController class and write code that retrieves the movie data and displays it in the browser using a view template. Be sure to build your application before proceeding.

Right-click the Controllers folder and create a new MoviesController controller. Select the following options:

  • Controller name: MoviesController. (This is the default. )
  • Template: Controller with read/write actions and views, using Entity Framework.
  • Model class: Movie (MvcMovie.Models).
  • Data context class: MovieDBContext (MvcMovie.Models).
  • Views: Razor (CSHTML). (The default.)

AddScaffoldedMovieController

Click Add. Visual Web Developer creates the following files and folders:

  • A MoviesController.cs file in the project’s Controllers folder.
  • Movies folder in the project’s Views folder.
  • Create.cshtml, Delete.cshtml, Details.cshtml, Edit.cshtml, and Index.cshtml in the new Views\Movies folder.

NewMovieControllerScreenShot

The ASP.NET MVC 3 scaffolding mechanism automatically created the CRUD (create, read, update, and delete) action methods and views for you. You now have a fully functional web application that lets you create, list, edit, and delete movie entries.

Run the application and browse to the Movies controller by appending /Movies to the URL in the address bar of your browser. Because the application is relying on the default routing (defined in the Global.asax file), the browser request http://localhost:xxxxx/Movies is routed to the default Index action method of the Moviescontroller. In other words, the browser request http://localhost:xxxxx/Movies is effectively the same as the browser request http://localhost:xxxxx/Movies/Index. The result is an empty list of movies, because you haven’t added any yet.

Creating a Movie

Select the Create New link. Enter some details about a movie and then click the Create button.

Clicking the Create button causes the form to be posted to the server, where the movie information is saved in the database. You’re then redirected to the /Movies URL, where you can see the newly created movie in the listing.

IndexWhenHarryMet

Create a couple more movie entries. Try the EditDetails, and Delete links, which are all functional.

Examining the Generated Code

Open the Controllers\MoviesController.cs file and examine the generated Index method. A portion of the movie controller with the Index method is shown below.

public class MoviesController : Controller
{
    private MovieDBContext db = new MovieDBContext();

    //
    // GET: /Movies/

    public ViewResult Index()
    {
        return View(db.Movies.ToList());
    }

The following line from the MoviesController class instantiates a movie database context, as described previously. You can use the movie database context to query, edit, and delete movies.

private MovieDBContext db = new MovieDBContext();

A request to the Movies controller returns all the entries in the Movies table of the movie database and then passes the results to the Index view.

Strongly Typed Models and the @model Keyword

Earlier in this tutorial, you saw how a controller can pass data or objects to a view template using the ViewBagobject. The ViewBag is a dynamic object that provides a convenient late-bound way to pass information to a view.

ASP.NET MVC also provides the ability to pass strongly typed data or objects to a view template. This strongly typed approach enables better compile-time checking of your code and richer IntelliSense in the Visual Web Developer editor. We’re using this approach with the MoviesController class and Index.cshtml view template.

Notice how the code creates a List object when it calls the View helper method in the Index action method. The code then passes this Movies list from the controller to the view:

public ViewResult Index()
{
    return View(db.Movies.ToList());
}

By including a @model statement at the top of the view template file, you can specify the type of object that the view expects. When you created the movie controller, Visual Web Developer automatically included the following @model statement at the top of the Index.cshtml file:

@model IEnumerable<MvcMovie.Models.Movie>

This @model directive allows you to access the list of movies that the controller passed to the view by using aModel object that’s strongly typed. For example, in the Index.cshtml template, the code loops through the movies by doing a foreach statement over the strongly typed Model object:

@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Title)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.ReleaseDate)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Genre)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Price)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", new { id=item.ID }) |
            @Html.ActionLink("Details", "Details", new { id=item.ID }) |
            @Html.ActionLink("Delete", "Delete", new { id=item.ID })
        </td>
    </tr>
}

Because the Model object is strongly typed (as an IEnumerable<Movie> object), each item object in the loop is typed as Movie. Among other benefits, this means that you get compile-time checking of the code and full IntelliSense support in the code editor:

ModelIntellisene

Working with SQL Server Compact

Entity Framework Code First detected that the database connection string that was provided pointed to a Moviesdatabase that didn’t exist yet, so Code First created the database automatically. You can verify that it’s been created by looking in the App_Data folder. If you don’t see the Movies.sdf file, click the Show All Files button in the Solution Explorer toolbar, click the Refresh button, and then expand the App_Data folder.

SDF_in_SolnExp

Double-click Movies.sdf to open Server Explorer. Then expand the Tables folder to see the tables that have been created in the database.

Note   If you get an error when you double-click Movies.sdf, make sure you’ve installed SQL Server Compact 4.0 (runtime + tools support). (For links to the software, see the list of prerequisites in part 1 of this tutorial series.) If you install the release now, you’ll have to close and re-open Visual Web Developer.

DB_explorer

There are two tables, one for the Movie entity set and then the EdmMetadata table. The EdmMetadata table is used by the Entity Framework to determine when the model and the database are out of sync.

Right-click the Movies table and select Show Table Data to see the data you created.

MoviesTable

Right-click the Movies table and select Edit Table Schema.

EditTableSchema

TableSchemaSM

Notice how the schema of the Movies table maps to the Movie class you created earlier. Entity Framework Code First automatically created this schema for you based on your Movie class.

When you’re finished, close the connection. (If you don’t close the connection, you might get an error the next time you run the project).

CloseConnection

You now have the database and a simple listing page to display content from it. In the next tutorial, we’ll examine the rest of the scaffolded code and add a SearchIndex method and a SearchIndex view that lets you search for movies in this database.

ASP.NET MVC part 4 Adding a Model

Adding a Model

In this section you’ll add some classes for managing movies in a database. These classes will be the “model” part of the ASP.NET MVC application.

You’ll use a .NET Framework data-access technology known as the Entity Framework to define and work with these model classes. The Entity Framework (often referred to as EF) supports a development paradigm calledCode First. Code First allows you to create model objects by writing simple classes. (These are also known as POCO classes, from “plain-old CLR objects.”) You can then have the database created on the fly from your classes, which enables a very clean and rapid development workflow.

Adding Model Classes

In Solution Explorer, right click the Models folder, select Add, and then select Class.

Name the class “Movie”.

CreateMovieClass

Add the following five properties to the Movie class:

public class Movie 
{
    public int ID { get; set; }
    public string Title { get; set; }
    public DateTime ReleaseDate { get; set; }
    public string Genre { get; set; }
    public decimal Price { get; set; }
}

We’ll use the Movie class to represent movies in a database. Each instance of a Movie object will correspond to a row within a database table, and each property of the Movie class will map to a column in the table.

In the same file, add the following MovieDBContext class:

 public class MovieDBContext : DbContext 
{
    public DbSet<Movie> Movies { get; set; } 
}

The MovieDBContext class represents the Entity Framework movie database context, which handles fetching, storing, and updating Movie class instances in a database. The MovieDBContext derives from the DbContextbase class provided by the Entity Framework. For more information about DbContext and DbSet, seeProductivity Improvements for the Entity Framework.

In order to be able to reference DbContext and DbSet, you need to add the following using statement at the top of the file:

using System.Data.Entity;

The complete Movie.cs file is shown below.

using System;
using System.Data.Entity;

namespace MvcMovie.Models  
{
    public class Movie
    {        public int ID { get; set; }
        public string Title { get; set; }        public DateTime ReleaseDate { get; set; }        public string Genre { get; set; }
        public decimal Price { get; set; }    }

    public class MovieDBContext : DbContext 
    {
        public DbSet<Movie> Movies { get; set; } 
    }
}

Creating a Connection String and Working with SQL Server Compact

The MovieDBContext class you created  handles the task of connecting to the database and mapping Movieobjects to database records. One question you might ask, though, is how to specify which database it will connect to. You’ll do that by adding connection information in the Web.config file of the application.

Open the application root Web.config file. (Not the Web.config file in the Views folder.) The image below show both Web.config files; open the Web.config file circled in red.

Add the following connection string to the <connectionStrings> element in the Web.config file.

    <add name="MovieDBContext" 
         connectionString="Data Source=|DataDirectory|Movies.sdf" 
         providerName="System.Data.SqlServerCe.4.0"/>

The following example shows a portion of the Web.config file with the new connection string added:

<configuration>
  <connectionStrings>
    <add name="MovieDBContext" 
         connectionString="Data Source=|DataDirectory|Movies.sdf" 
         providerName="System.Data.SqlServerCe.4.0"/>
    <add name="ApplicationServices"
         connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true"
         providerName="System.Data.SqlClient" />
  </connectionStrings>

This small amount of code and XML is everything you need to write in order to represent and store the movie data in a database.

Next, you’ll build a new MoviesController class that you can use to display the movie data and allow users to create new movie listings.

ASP.NET MVC part 3 Adding a View

Adding a View

In this section you’re going to modify the HelloWorldController class to use view template files to cleanly encapsulate the process of generating HTML responses to a client.

You’ll create a view template file using the new Razor view engine introduced with ASP.NET MVC 3. Razor-based view templates have a .cshtml file extension, and provide an elegant way to create HTML output using C#. Razor minimizes the number of characters and keystrokes required when writing a view template, and enables a fast, fluid coding workflow.

Start by using a view template with the Index method in the HelloWorldController class. Currently the Indexmethod returns a string with a message that is hard-coded in the controller class. Change the Index method to return a View object, as shown in the following:

public ActionResult Index() 
{ 
    return View(); 
}

This code uses a view template to generate an HTML response to the browser. In the project, add a view template that you can use with the Index method. To do this, right-click inside the Index method and click Add View.

The Add View dialog box appears. Leave the defaults the way they are and click the Add button:

The MvcMovie\Views\HelloWorld folder and the MvcMovie\Views\HelloWorld\Index.cshtml file are created. You can see them in Solution Explorer:

The following shows the Index.cshtml file that was created:

HelloWorldIndex

Add some HTML under the <h2> tag. The modified MvcMovie\Views\HelloWorld\Index.cshtml file is shown below.

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>Hello from our View Template!</p>

Run the application and browse to the HelloWorld controller (http://localhost:xxxx/HelloWorld). The Indexmethod in your controller didn’t do much work; it simply ran the statement return View(), which specified that the method should use a view template file to render a response to the browser. Because you didn’t explicitly specify the name of the view template file to use, ASP.NET MVC defaulted to using the Index.cshtml view file in the \Views\HelloWorld folder. The image below shows the string hard-coded in the view.

Looks pretty good. However, notice that the browser’s title bar says “Index” and the big title on the page says “My MVC Application.” Let’s change those.

Changing Views and Layout Pages

First, you want to change the “My MVC Application” title at the top of the page. That text is common to every page. It actually is implemented in only one place in the project, even though it appears on every page in the application. Go to the /Views/Shared folder in Solution Explorer and open the _Layout.cshtml file. This file is called a layout page and it’s the shared “shell” that all other pages use.

_LayoutCshtml

Layout templates allow you to specify the HTML container layout of your site in one place and then apply it across multiple pages in your site. Note the @RenderBody() line near the bottom of the file. RenderBody is a placeholder where all the view-specific pages you create show up, “wrapped” in the layout page. Change the title heading in the layout template from “My MVC Application” to “MVC Movie App”.

   <div id="title">
      <h1>MVC Movie App</h1>
  </div>

Run the application and notice that it now says “MVC Movie App”. Click the About link, and you see how that page shows “MVC Movie App”, too. We were able to make the change once in the layout template and have all pages on the site reflect the new title.

The complete _Layout.cshtml file is shown below:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>@ViewBag.Title</title>
    <link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
    <script src="@Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
</head>
<body>
    <div class="page">
        <header>
            <div id="title">
                <h1>MVC Movie App</h1>
            </div>
            <div id="logindisplay">
                @Html.Partial("_LogOnPartial")
            </div>
            <nav>
                <ul id="menu">
                    <li>@Html.ActionLink("Home", "Index", "Home")</li>
                    <li>@Html.ActionLink("About", "About", "Home")</li>
                </ul>
            </nav>
        </header>
        <section id="main">
            @RenderBody()
        </section>
        <footer>
        </footer>
    </div>
</body>
</html>

Now, let’s change the title of the Index page (view).

Open MvcMovie\Views\HelloWorld\Index.cshtml. There are two places to make a change: first, the text that appears in the title of the browser, and then in the secondary header (the <h2> element). You’ll make them slightly different so you can see which bit of code changes which part of the app.

@{
    ViewBag.Title = "Movie List";
}

<h2>My Movie List</h2>

<p>Hello from our View Template!</p>

To indicate the HTML title to display, the code above sets a Title property of the ViewBag object (which is in the Index.cshtml view template). If you look back at the source code of the layout template, you’ll notice that the template uses this value in the <title> element as part of the <head> section of the HTML. Using this approach, you can easily pass other parameters between your view template and your layout file.

Run the application and browse to http://localhost:xx/HelloWorld. Notice that the browser title, the primary heading, and the secondary headings have changed. (If you don’t see changes in the browser, you might be viewing cached content. Press Ctrl+F5 in your browser to force the response from the server to be loaded.)

Also notice how the content in the Index.cshtml view template was merged with the _Layout.cshtml view template and a single HTML response was sent to the browser. Layout templates make it really easy to make changes that apply across all of the pages in your application.

Our little bit of “data” (in this case the “Hello from our View Template!” message) is hard-coded, though. The MVC application has a “V” (view) and you’ve got a “C” (controller), but no “M” (model) yet. Shortly, we’ll walk through how create a database and retrieve model data from it.

Passing Data from the Controller to the View

Before we go to a database and talk about models, though, let’s first talk about passing information from the controller to a view. Controller classes are invoked in response to an incoming URL request. A controller class is where you write the code that handles the incoming parameters, retrieves data from a database, and ultimately decides what type of response to send back to the browser. View templates can then be used from a controller to generate and format an HTML response to the browser.

Controllers are responsible for providing whatever data or objects are required in order for a view template to render a response to the browser. A view template should never perform business logic or interact with a database directly. Instead, it should work only with the data that’s provided to it by the controller. Maintaining this “separation of concerns” helps keep your code clean and more maintainable.

Currently, the Welcome action method in the HelloWorldController class takes a name and a numTimesparameter and then outputs the values directly to the browser. Rather than have the controller render this response as a string, let’s change the controller to use a view template instead. The view template will generate a dynamic response, which means that you need to pass appropriate bits of data from the controller to the view in order to generate the response. You can do this by having the controller put the dynamic data that the view template needs in a ViewBag object that the view template can then access.

Return to the HelloWorldController.cs file and change the Welcome method to add a Message and NumTimesvalue to the ViewBag object. ViewBag is a dynamic object, which means you can put whatever you want in to it; the ViewBag object has no defined properties until you put something inside it. The completeHelloWorldController.cs file looks like this:

using System.Web;
using System.Web.Mvc;

namespace MvcMovie.Controllers
{
    public class HelloWorldController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult Welcome(string name, int numTimes = 1)
        {
            ViewBag.Message = "Hello " + name;
            ViewBag.NumTimes = numTimes;

            return View();
        }
    }
}

Now the ViewBag object contains data that will be passed to the view automatically.

Next, you need a Welcome view template! In the Debug menu, select Build MvcMovie to make sure the project is compiled.

BuildHelloWorld

Then right-click inside the Welcome method and click Add View. Here’s what the Add View dialog box looks like:

Click Add, and then add the following code under the <h2> element in the new Welcome.cshtml file. You’ll create a loop that says “Hello” as many times as the user says it should. The complete Welcome.cshtml file is shown below.

@{
    ViewBag.Title = "Welcome";
}

<h2>Welcome</h2>

<ul> 
   @for (int i=0; i < ViewBag.NumTimes; i++) { 
      <li>@ViewBag.Message</li> 
   } 
</ul>

Run the application and browse to the following URL:

http://localhost:xx/HelloWorld/Welcome?name=Scott&numtimes=4

Now data is taken from the URL and passed to the controller automatically. The controller packages the data into a ViewBag object and passes that object to the view. The view then displays the data as HTML to the user.

Well, that was a kind of an “M” for model, but not the database kind. Let’s take what we’ve learned and create a database of movies.

ASP.NET MVC part 2 Adding a Controller

Adding a Controller

MVC stands for model-view-controller. MVC is a pattern for developing applications that are well architected and easy to maintain. MVC-based applications contain:

  • Controllers: Classes that handle incoming requests to the application, retrieve model data, and then specify view templates that return a response to the client.
  • Models: Classes that represent the data of the application and that use validation logic to enforce business rules for that data.
  • Views: Template files that your application uses to dynamically generate HTML responses.

We’ll be covering all these concepts in this tutorial series and show you how to use them to build an application.

Let’s begin by creating a controller class. In Solution Explorer, right-click the Controllers folder and then select Add Controller.

Name your new controller “HelloWorldController”. Leave the default template as Empty controller and clickAdd.

AddHelloWorldController

Notice in Solution Explorer that a new file has been created named HelloWorldController.cs. The file is open in the IDE.

Inside the public class HelloWorldController block, create two methods that look like the following code. The controller will return a string of HTML as an example.

using System.Web;
using System.Web.Mvc; 
 
namespace MvcMovie.Controllers 
{ 
    public class HelloWorldController : Controller 
    { 
        // 
        // GET: /HelloWorld/ 
 
        public string Index() 
        { 
            return "This is my <b>default</b> action..."; 
        } 
 
        // 
        // GET: /HelloWorld/Welcome/ 
 
        public string Welcome() 
        { 
            return "This is the Welcome action method..."; 
        } 
    } 
}

Your controller is named HelloWorldController and the first method above is named Index. Let’s invoke it from a browser. Run the application (press F5 or Ctrl+F5). In the browser, append “HelloWorld” to the path in the address bar. (For example, in the illustration below, it’s http://localhost:43246/HelloWorld.) The page in the browser will look like the following screenshot. In the method above, the code returned a string directly. You told the system to just return some HTML, and it did!

ASP.NET MVC invokes different controller classes (and different action methods within them) depending on the incoming URL. The default mapping logic used by ASP.NET MVC uses a format like this to determine what code to invoke:

/[Controller]/[ActionName]/[Parameters]

The first part of the URL determines the controller class to execute. So /HelloWorld maps to theHelloWorldController class. The second part of the URL determines the action method on the class to execute. So /HelloWorld/Index would cause the Index method of the HelloWorldController class to execute. Notice that we only had to browse to /HelloWorld and the Index method was used by default. This is because a method named Index is the default method that will be called on a controller if one is not explicitly specified.

Browse to http://localhost:xxxx/HelloWorld/Welcome. The Welcome method runs and returns the string “This is the Welcome action method…”. The default MVC mapping is /[Controller]/[ActionName]/[Parameters]. For this URL, the controller is HelloWorld and Welcome is the action method. You haven’t used the[Parameters] part of the URL yet.

Let’s modify the example slightly so that you can pass some parameter information from the URL to the controller (for example, /HelloWorld/Welcome?name=Scott&numtimes=4). Change your Welcome method to include two parameters as shown below. Note that the code uses the C# optional-parameter feature to indicate that the numTimes parameter should default to 1 if no value is passed for that parameter.

public string Welcome(string name, int numTimes = 1) {
     return HttpUtility.HtmlEncode("Hello " + name + ", NumTimes is: " + numTimes);
}

Run your application and browse to the example URL (http://localhost:xxxx/HelloWorld/Welcome?name=Scott&numtimes=4). You can try different values for name and numtimes in the URL. The system automatically maps the named parameters from the query string in the address bar to parameters in your method.

In both these examples the controller has been doing the “VC” portion of MVC — that is, the view and controller work. The controller is returning HTML directly. Ordinarily you don’t want controllers returning HTML directly, since that becomes very cumbersome to code. Instead we’ll typically use a separate view template file to help generate the HTML response. Let’s look next at how we can do this.

ASP.NET MVC part 1 Intro to ASP.NET MVC 3

What You’ll Build

You’ll implement a simple movie-listing application that supports creating, editing, and listing movies from a database. Below are two screenshots of the application you’ll build. It includes a page that displays a list of movies from a database:

MoviesWithVariousSm

The application also lets you add, edit, and delete movies, as well as see details about individual ones. All data-entry scenarios include validation to ensure that the data stored in the database is correct.

Skills You’ll Learn

Here’s what you’ll learn:

  • How to create a new ASP.NET MVC project.
  • How to create ASP.NET MVC controllers and views.
  • How to create a new database using the Entity Framework Code First paradigm.
  • How to retrieve and display data.
  • How to edit data and enable data validation.

Getting Started

Start by running Visual Web Developer 2010 Express (“Visual Web Developer” for short) and select New Project from the Start page.

Visual Web Developer is an IDE, or integrated development environment. Just like you use Microsoft Word to write documents, you’ll use an IDE to create applications. In Visual Web Developer there’s a toolbar along the top showing various options available to you. There’s also a menu that provides another way to perform tasks in the IDE. (For example, instead of selecting New Project from the Start page, you can use the menu and selectFile > New Project.)

Creating Your First Application

You can create applications using either Visual Basic or Visual C# as the programming language. Select Visual C# on the left and then select ASP.NET MVC 3 Web Application. Name your project “MvcMovie” and then click OK. (If you prefer Visual Basic, switch to the Visual Basic version of this tutorial.)

In the New ASP.NET MVC 3 Project dialog box, select Internet Application. Check Use HTML5 markupand leave Razor as the default view engine.

Click OK. Visual Web Developer used a default template for the ASP.NET MVC project you just created, so you have a working application right now without doing anything! This is a simple “Hello World!” project, and it’s a good place to start your application.

From the Debug menu, select Start Debugging.

Notice that the keyboard shortcut to start debugging is F5.

F5 causes Visual Web Developer to start a development web server and run your web application. Visual Web Developer then launches a browser and opens the application’s home page. Notice that the address bar of the browser says localhost and not something like example.com. That’s because localhost always points to your own local computer, which in this case is running the application you just built. When Visual Web Developer runs a web project, a random port is used for the web server. In the image below, the random port number is 43246. When you run the application, you’ll probably see a different port number.

Right out of the box this default template gives you two pages to visit and a basic login page. The next step is to change how this application works and learn a little bit about ASP.NET MVC in the process. Close your browser and let’s change some code.

Hello World WP7 – Silverlight Style Mobile Tools Team Windows Phone Developer Tools Team Blog

If you are a Silverlight programmer, you already know a lot about Windows Phone 7 programming. If you are new to Silverlight or to Windows Phone 7, don’t worry, we will go over several easy to use concepts using this fun littleHello Word application, Silverlight style. What do I mean by that you might ask? We are bored of the Hello World apps. Let us create an exciting simple video player that will rotate as our Hello World application, Silverlight Style.

Let us get started. First install the Windows Phone Developer Tools Beta. You will get everything you need to get started with Windows Phone 7 development. Even if you are new to Microsoft platforms or tools, follow along with this step by step guide. Final solution is attached at the bottom of this page.

Step1 : Create a new Windows Phone Application

Open Microsoft Visual Studio 2010 Express for Windows Phone or VS2010 pro/premium/ultimate. I am using Visual Studio 2010 Express for Windows Phone. Also, I have enabled Expert Settings under Tools > Settings > Expert Settings. Select File > Create New Project (Ctrl+Shift+N). Select the Windows Phone Application template and give the application name as CrazyVideoApp.

You will see Designer where the Application UI is displayed, XAML editor that shows the UI definition and several tool windows around.

Step2: Customize UI

Select page name TextBlock in the designer and edit the name in the Property tool window. If the Property tool window is not visible, you can right click in the designer and select Properties. Change the Text property to crazy video. Similarly change the MY APPLICATION to DATA BINDING.

Step3: Add Video clip

From the Toolbox window, drag and drop a MediaElement control (at runtime plays a video) on to the designer. Resize it so that it is a little bigger. If the Toolbox window is not visible, you can select it from the View menu.

Now that we have a MediaElement that can play a video, let us add a video clip. Right click on the Project and select Add -> Existing Item.

In this case I am picking a movie.wmv file on the desktop. You can download this in the attached source code. Currently we support the following video format and codecs on the Emulator: WMV (VC1 – Main and Simple profile). The video provided in the solution is encoded as WMV (VC1-Main profile).  Now we need to wire up the MediaElement to the media file we added. We can do that by simply selecting the MediaElement we added in the designer and changing the Source property to movie.wmv

By default the MediaElement control will start playing the media once the application is launched.

Step 4: Debug It

Let us run it (in debug mode) by hitting F5. You will see the Windows Phone Emulator launch and the app get deployed to it. Then, you will see the app running in the Emulator and the Visual Studio goes into Debug mode.

Step 5: Lets go crazy

Silverlight does not support complete 3D. It supports what is 2.5D through Perspective Transforms to simulate 3D. Let us add some perspective transform to make our video rotate in 3D. Add the following code in the XAML.

<MediaElement Height=”233″ HorizontalAlignment=”Left” Margin=”24,33,0,0″ Name=”mediaElement1″ VerticalAlignment=”Top” Width=”383″ Source=”movie.wmv”>
<MediaElement.Projection>
<PlaneProjection x:Name=”projector” />
</MediaElement.Projection>
</MediaElement>

All we are doing here is setting up a Plane Projection called projector that we will use to rotate the video in the 3D space.

Add a Slider control below the MediaElement and set its Maximum to 360 so that we can rotate from 0 to 360 degrees.

We want to rotate the MediaElement when we drag the slider. So we use Element to Element Databinding to do this trick easily.

Let us use the Property editor to app databinding. Select the little square next to the Value property and selectApply Data Binding… option.

In the popup window, select ElementName in the first listbox and projector in the second listbox.

Now select Path: expandable property shown above and Select RotationY property. This will generate the following code in the Slider XAML tag: Value=”{Binding Path=RotationY, Mode=TwoWay, ElementName=projector}”

What we did so far is to tell SL engine “Whenever the slider1’s Value property changes, take that value and set it as the projector’s RotationY property”. So, when we drag the slider, the video rotates on tis Y Axis.

Add another slider next to the MediaElement, set the Orientation to Vertical and instead of binding Value toRotationY, bind it to RotationX.

 

Hit F5 to see our crazy video app. Drag the sliders to see the video rotate on X and Y axis.

Role-based access Silverlight Applications

Security is a key component of applications and something that developers often struggle with to get right. How do you authenticate a user? How do you integrate roles and use them to show or hide different parts of a screen? These and other questions commonly come up as I talk with developers working on ASP.NET and Silverlight applications.

I was recently presenting a workshop on Silverlight at the DevConnections conference in Orlando and had a question from the audience on how I handle security roles in Silverlight applications. Since I had just implemented a security mechanism for a customer I gave a brief response but didn’t have a sample application available to share to point people in the right direction. After the workshop was over I put together a sample application to demonstrate one potential approach for accessing user names and roles. I’ll walk through the sample application in this post and highlight the key components.

The goal of the post isn’t to dictate how to authenticate users since every application has unique requirements. However, I will discuss general techniques for accessing user names and working with roles to block access to views and show or hide controls.

Security Techniques

Silverlight applications can take advantage of Windows and Forms authentication techniques and can integrate user roles into the mix as well. However, unless you use WCF RIA Services on the backend you’ll need to write the plumbing code to authenticate a user if you need to do it directly within the application. WCF RIA Services projects provide login and registration screens out of the box that leverage Forms authentication by default. You can view a walk-through of the WCF RIA Services authentication process here http://msdn.microsoft.com/en-us/library/ee942449(VS.91).aspx.

WCF RIA Services also provides a means for accessing an authenticated user’s user name and roles by using a WebContext object (seehttp://msdn.microsoft.com/en-us/library/ee707361(VS.91).aspx). This isn’t possible out-of-the-box in a standard Silverlight application unless you write custom code to handle it. If WCF RIA Services is appropriate for your project then it’s a great way to go for data exchange and security tasks. If you won’t be using WCF RIA Services then this post will provide insight into other techniques that can be used.

Most of the Silverlight Line of Business (LOB) applications I’ve worked on authenticate the user at the page level using Windows authentication. If the user can’t authenticate into the page then the Silverlight application is never displayed. With out-of-browser applications the Windows user account can be passed through and accessed as calls to a service are made. The sample application available with this post assumes that authentication occurs at the page level as opposed to within the Silverlight application itself.

Accessing a User’s Identity

To access an authenticated user’s user name within a Silverlight application you can either pass the user name into the object tag’s initialization parameter (called “initParams”) or call a service that returns the user name. An example of passing in the user name using the initParams option within an ASP.NET page that is hosting the object tag is shown next:

<param name="initParams" value="UserName=<%=User.Identity.Name%>" />

Within App.xaml.cs you can access the initParams parameters and store them. The code below shows how to do this and add initParams values into the application resources so that they can be accessed throughout the application.

private void Application_Startup(object sender, StartupEventArgs e)
{
    ProcessInitParams(e.InitParams);
    this.RootVisual = new MainPage();
}

private void ProcessInitParams(IDictionary<string, string> initParams)
{
    if (initParams != null)
    {
        foreach (var item in initParams)
        {
            this.Resources.Add(item.Key, item.Value);
        }
    }
}

I don’t personally like to embed the user name into the object tag unless it’s simply going to be displayed in the application. If you’ll be doing look-ups against different databases or other resources based upon the user name then it’s better to let a service resolve the user name dynamically so that it can’t be spoofed. Otherwise, a user that authenticated into the application could potentially change the user name defined in initParams and bypass security.

To access the user name using a service you can create a WCF security service as shown next and add an operation that is responsible for returning the user name. The easiest way to create the service is to add a Silverlight-enabled WCF Service into the Web project.

[ServiceContract(Namespace = "YourNamespace")]
[SilverlightFaultBehavior]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class SecurityService
{
    [OperationContract]
    public string GetLoggedInUserName()
    {
        return new SecurityRepository().GetUserName(OperationContext.Current);
    }

    [OperationContract]
    public List<Role> GetRoles()
    {
        return new SecurityRepository().GetRoles();
    }

    [OperationContract]
    public UserSecurity GetUserSecurity()
    {
        return new SecurityRepository().GetUserSecurity(OperationContext.Current);
    }
}

The previous code contains a GetLoggedInUserName() operation that makes a call into a SecurityRepository class’s GetUserName() method to access the user name. GetUserName() accesses the user name through the OperationContext object’s ServiceSecurityContext property which provides access to the user’s identity object (note that specific configuration changes must be made for this object to be useful – see the sample project’s web.config file for more details).

The following code shows the SecurityRepository class. The class simulates roles by adding them directly into the code but could easily be enhanced to retrieve roles from a database or other store.

public class SecurityRepository
{
    List<Role> _Roles = new List<Role>();

    public SecurityRepository()
    {
         //Simulate roles 

        _Roles.Add(new Role { Name = "Admin" });
        _Roles.Add(new Role { Name = "Editor" });
        _Roles.Add(new Role { Name = "User" });
    }

    public string GetUserName(OperationContext opContext)
    {
        return GetOpContextUserName(opContext);
    }

    public List<Role> GetRoles()
    {
        return _Roles;
    }

    public UserSecurity GetUserSecurity(OperationContext opContext)
    {
        var userName = GetOpContextUserName(opContext);

        if (userName != null)
        {
            return new UserSecurity { UserName = userName, Roles = _Roles };
        }
        return null;
    }

    private string GetOpContextUserName(OperationContext opContext)
    {
        return (opContext.ServiceSecurityContext != null &&
                opContext.ServiceSecurityContext.WindowsIdentity != null) ? opContext.ServiceSecurityContext.WindowsIdentity.Name : null;
    }
}

The GetUserSecurity() method provides a way for the Silverlight application to make a single call and get the user name and roles for the authenticated user. This method is called by the Silverlight client and used to show and hide controls within the application. Let’s take a look at how that process works.

Building a SecurityManager for Silverlight

The WCF service shown earlier provides a way for a Silverlight application to retrieve a user name and roles. How do you go about calling the service and storing the resulting information? For a recent customer application I created a SecurityManager class that was responsible for storing user name and role information and exposing properties such as IsAdmin and IsEditor to handle determining what role a user was in. It went through a service agent class that was responsible for calling the WCF service and returning the data to the SecurityManager. By going this route a single class is responsible for security which avoids scattering security logic throughout an application. The following code shows the SecurityManager class available with the sample application.

public class SecurityManager : ISecurityManager
{
    public ISecurityServiceAgent SecurityServiceAgent { get; set; }
    public event EventHandler UserSecurityLoaded;

    public SecurityManager()
    {
        SecurityServiceAgent = new SecurityServiceAgent();
        GetUserSecurityDetails();
    }

    public void OnUserRolesLoaded(object sender, EventArgs e)
    {
        if (UserSecurityLoaded != null)
        {
            UserSecurityLoaded(sender, e);
        }
    }

    #region Properties

    public ObservableCollection<Role> UserRoles { get; set; }
    public string UserName { get; set; }

    public bool IsAdmin
    {
        get
        {
            if (UserRoles == null) return false;
            return UserIsInAnyRole("Admin");
        }
    }

    public bool IsInUserRole
    {
        get
        {
            if (UserRoles == null) return false;
            return (UserRoles.Count == 1 && UserRoles.Any(r => r.Name == "User"));
        }
    }

    public bool IsValidUser
    {
        get { return UserName != null && (UserRoles != null && UserRoles.Count > 0); }
    }

    public bool IsEditor
    {
        get
        {
            if (UserRoles == null) return false;
            return IsAdmin || UserIsInAnyRole("Editor", "HRAdmin");
        }
    }

    public bool IsUserSecurityLoadComplete { get; set; }

    #endregion

    private void GetUserSecurityDetails()
    {
        SecurityServiceAgent.CallService<GetUserSecurityCompletedEventArgs>(
        (s, args) =>
        {
            IsUserSecurityLoadComplete = true;
            UserRoles = args.Result.Roles;
            UserName = args.Result.UserName;
            OnUserRolesLoaded(this, EventArgs.Empty);
        });
    }

    //Determine if a user has rights to see an application view or not
    public bool CheckUserAccessToUri(Uri uri)
    {
        if (UserRoles != null)
        {
            string screenUri = uri.ToString().ToLower();
            if (screenUri.StartsWith("/home"))
                return IsValidUser;
            if (screenUri.StartsWith("/customers"))
                return IsAdmin;
            if (screenUri.StartsWith("/about"))
                return IsValidUser;
        }
        return false;
    }

    public bool UserIsInRole(string role)
    {
        if (UserRoles == null) return false;
        return UserRoles.Any(r => r.Name == role);
    }

    public bool UserIsInAnyRole(params string[] roles)
    {
        if (UserRoles == null) return false;
        return (from ur in UserRoles
                from r in roles
                where ur.Name.Contains(r)
                select r).Any();
    }
}

The key part of the SecurityManager class is found in the constructor where a call is made to another class named SecurityServiceAgent (a “service agent” that specializes in data retrieval) to retrieve the user name and roles from the WCF security service shown earlier. Since the service call is asynchronous an event is defined in SecurityManager named UserSecurityLoaded that is raised once the data is loaded in the Silverlight client.[

In addition to getting and storing user data, the SecurityManager class also has methods such as UserIsInAnyRole() to check if the user is a member of an array of roles, UserIsInRole() to check if they’re in a specific role and CheckUserAccessToUri() to verify whether or not they have access to a specific view. Properties such as IsAdmin and IsEditor provide a simple way for consumers of the SecurityManager class to check if a user is in a role specific to the application.

Using the SecurityManager to Handle Roles and User Names

The SecurityManager class can be used directly in views or within ViewModel classes. When using the MVVM pattern a property can be added into a ViewModel base class (a class that all ViewModel classes derive from) as shown next:

public ISecurityManager SecurityManager { get; set; }

This property allows security functionality to be available across all ViewModel classes. The sample application contains two ViewModel classes that use SecurityManager named MainPageViewModel and HomeViewModel. MainPageViewModel uses the SecurityManager class to render the user name in the MainPage.xaml view and hide any HyperlinkButton controls that a user shouldn’t be able to see. The following code shows the MainPageViewModel class.

public class MainPageViewModel : ViewModelBase
{
    private bool _IsAdmin;
    private string _UserName;

    public MainPageViewModel()
    {
        if (!IsDesignTime) SecurityManager.UserSecurityLoaded += SecurityManagerUserSecurityLoaded;
    }

    public bool IsAdmin
    {
        get
        {
            return _IsAdmin;
        }
        private set
        {
            if (_IsAdmin != value)
            {
                _IsAdmin = value;
                OnNotifyPropertyChanged("IsAdmin");
            }
        }
    }

    public string UserName
    {
        get
        {
            return _UserName;
        }
        private set
        {
            if (_UserName != value)
            {
                _UserName = value;
                OnNotifyPropertyChanged("UserName");
            }
        }
    }

    void SecurityManagerUserSecurityLoaded(object sender, EventArgs e)
    {
        IsAdmin = SecurityManager.IsAdmin;
        UserName = SecurityManager.UserName;
    }
}

MainPageViewModel starts by attaching to the SecurityManager’s UserSecurityLoaded event. Once the event fires, SecurityManagerUserSecurityLoaded is called and the IsAdmin and UserName properties are assigned to the ViewModel’s properties. These properties are then bound to controls in the view using standard Silverlight data binding techniques. The IsAdmin property is bound to HyperlinkButton controls and used to show or hide the controls based on if the user is in the “Admin” role or not. A value converter is used in the view to handle converting the Boolean value to a Visibility enumeration value. The UserName property is bound to a TextBlock control that displays the user name in the interface.

HomeViewModel uses the SecurityManager class to determine if edit controls that allow customer information to be saved and edited should be present or not. If the user is in the Admin or Editor role then the controls are shown. If not, the controls are hidden.

Securing Views

Although accessing user name and role functionality is important in order to customize the user interface based upon the user’s security rights, you’ll also need to secure individual views in many cases. For example, the MainPageViewModel defines an IsAdmin property (shown previously) that is used to show or hide a HyperlinkButton to prevent a user from going to a specific view. However, if the user knows the path to the view they can type it directly into the browser’s URL and load the view directly which bypasses the intended security. To prevent this, the CheckUserAccessToUri() method in the SecurityManager class can be used in conjunction with the Navigating event of the Frame within MainPage.xaml (the Frame control is included since the sample project uses the Silverlight navigation application project template).

The following snippet shows the code that handles checking if a user has access to a specific view as the Frame in MainPage.xaml loads content. The code shown in MainPage_Loaded handles attaching to the Frame’s Navigating event. When the event is raised the code in the ContentFrame_Navigating event handler cancels the Navigating event if the user isn’t determined to be a valid user. It also makes the call to the CheckUserAccessToUri() method to determine if the user is allowed to get to the view that the content Frame is attempting to load. If the user doesn’t access, a view named AccessDenied.xaml is loaded which displays the appropriate “Access Denied” error message.

void MainPage_Loaded(object sender, RoutedEventArgs e)
{
    PeopleEventBus.OperationCompleted += PeopleEventBus_OperationCompleted;
    ViewModel = (MainPageViewModel)this.Resources["ViewModel"];
    ViewModel.SecurityManager.UserSecurityLoaded += SecurityManagerUserSecurityLoaded;

    ContentFrame.Navigating += ContentFrame_Navigating;
    ContentFrame.Navigated += ContentFrame_Navigated;
}

void SecurityManagerUserSecurityLoaded(object sender, EventArgs e)
{
    //Cause frame to navigate to view user originally wanted to see
    ViewModel.SecurityManager.UserSecurityLoaded -= SecurityManagerUserSecurityLoaded;
    ContentFrame.Navigate(ContentFrame.Source);
}

private void ContentFrame_Navigating(object sender, NavigatingCancelEventArgs e)
{
    //No user name or roles found
    if (!ViewModel.SecurityManager.IsValidUser)
    {
        e.Cancel = true;
        return;
    }

    //Check if user has access to page that they're trying to nagivate to
    var hasAccess = ViewModel.SecurityManager.CheckUserAccessToUri(e.Uri);
    if (!hasAccess)
    {
        ContentFrame.Content = new AccessDenied();
        e.Cancel = true;
    }
}

Security is an important part of Line of Business (LOB) applications and something that definitely must be thought through and planned carefully. In this post you’ve seen different ways to access a user name and associated roles in a Silverlight application. You’ve also seen how a SecurityManager class can be created to perform security checks that are used by ViewModel classes to show or hide controls. To the person in the DevConnections workshop mentioned at the beginning, thanks for asking the question and I hope the sample application (available below) helps get you started in the right direction integrating security features into your Silverlight applications.

Download the sample application code here.

WP7 Application Icon and Application Tile Icon

What is Application Icon?

Basically the application icon is the image that displays for your application in the phone’s application list.

According to the latest version of the Windows Phone 7 Application Certification Requirements (Here’s a direct link to the PDF file)the application icons should meet the following requirements:

tip52-6 AppIcon

  • PNG file format
  • 62 x 62 pixels

What is Application Tile Icon?

Basically an application tile is the image (of your application) that appears when users pins your application to the start screen. 

According to the latest version of the Windows Phone 7 Application Certification Requirements (Here’s a direct link to the PDF file)the application icons should meet the following requirements:tip52-8

AppTile

  • PNG file format
  • 173x 173pixels

How to add a new Application Icon?

By default when you create a new Windows Phone 7 application a sample ApplicationIcon.png image is automatically generated.  In order to change this image at first we have to add our new image to our project and set its build action to Content.

NOTE: You can also take a look at our article: WP7 working with Images: Content vs Resource build action

tip52-0tip52-3

After that you have two options either to use the VisualStudio Project Designer or WMAppManifest.xml file.

  • Change Application Icon using the VisualStudio Project Designer

In order to change the application icon just follow the steps:

1. Right click on your project in VisualStudio and select Properties.

2. Go to Application Tab where you will find a section called  “Icon”.

tip52-1 tip52-2

3.Just select from the combo your new icon:

tip52-4

  • Change Application Icon using WMAppManifest.xml file

Windows Phone projects have an auto-generated XML manifest file that contains phone application metadata. The XML manifest file includes information such as IconPath, product IDs, versioning details, runtime types, paths to resources, phone capabilities, and other application-specific information.

So in order to change the application icon just go to WMAppManifest.xml and change the IconPath tag like for example:

tip52-5

1
<IconPath IsRelative="true" IsResource="false">MyAppIcon.png</IconPath>

NOTE: For any reference you can also take a look at MSDN documentation.

How to add a new Application Tile Icon?

By default when you create a new Windows Phone 7 application a sample Background.png image is automatically generated.  In order to change this image at first we have to add our new image to our project and set its build action to Content. After that you have two options either to use the VisualStudio Project Designer or WMAppManifest.xml file.

  • Change Application Tile Icon using the VisualStudio Project Designer

Go to Application Tab(as explained in the previous point) where you will find a section called  “Background images”.

tip52-7

  • Change Application Icon using WMAppManifest.xml file In order to change the application tile icon just go toWMAppManifest.xml and change the BackgroundImageURI tag like for example:
1
2
3
4
5
6
7
<PrimaryToken TokenID="WP7SampleApp52Token" TaskName="_default">
  <TemplateType5>
    <BackgroundImageURI IsRelative="true" IsResource="false">AppTile.png</BackgroundImageURI>
    <Count>0</Count>
    <Title>WP7SampleApp52</Title>
  </TemplateType5>
</PrimaryToken>

That was all about how to change the Application Icon and Application Tile Icon of a Windows Phone 7 Application with new ones. Here is the source code:

Silverlight 5 new features

As all of us know silverlight5 has been released at MIX2011 by Scott Gu. If you want to start exploring SL5 features its time to start and do it now. Sl5 moves development more towards WPF, so some of the benefits that WPF developers are enjoyed that have been now added to SL5.

How to get Started with this Developer’s product ?

  • Install VS2010 SP1 from www.silverlight.net
  • Install Silverlight5 Beta Tools for VS2010 from here
  • Optionally install the Expression Blend Preview does SL5 Beta

Binding

  • We can place Breakpoints in XAML for debugging. In the editor directly can put breakpoint and debug in editor check or error messages.
  • Ancestor Relative Source for Binding to a property on parent control.
  • Binding now possible in style setters
    Implicit Data Templates

Media

  • New support for Low latency sound effects using the Sound Effect API. No more round robin queue. It’s fast and very responsive. Since the sound effects, sound effect instances will be reuse sound effects inside the applications.
  • We have Variable Speed Playback ( “Trick Play”). There is no audio support for beta only. It will be there in RC/ RTM
  • H 264 media is now decoded as hardware for a huge performance boost.

Text

  • Text tracking and leading control
  • Linked Rick Text Boxes for seamless workflow and multi –column text

Input

  • Click Count property for multi-click support, Now we can get number of clicks user have done
    • For example Double click
  • Listbox / ComboBox controls have type-ahead text searching

Full-Trust Applications

  • Through Group Policy settings, elevated trust available in browser foe signed applications
    • Including keyboard support in full-screen mode support kiosk-type applications
    • Windows-only for Beta
  • Un restricted File System Access
    • No longer restricted to “My Documents”
  • Native OS Windows Support

Graphics

  • Graphics stack improved using lessons learned from mobile, such as independent animations.
  • XNA 3D API for low-level access.
  • SL5 has XNA .3D API for low-level access to GPU, vertex shades and 3D primitives
  • Also works as an immediate mode 2d API

Performance Improvements

  • Improved XAML parse times for User Controls and Resource Dictionaries
  • 90% performance improvement in ClientHttpWebRequest scenarios
  • Hardware accelerated rendering in IE9, windowless (SL5 applications ) mode using the new SurfacePresenter APIs

Others

  • Create custom markup extensions
  • In-Browser HTML support
  • Default filename in the Save File Dialog
  • Many more fixes and improvements throughout the product

Seems that Ms has taken the feedback and implemented the same things that developers or customers asked for. I am exciting about this release and start playing with SL5 and if you can find any bugs in Beta, you can post at connect.microsoft.com for the fix and support.