Exercise 3: Creating the Edit View

In this exercise, you will learn how to create a form to allow store managers to edit an Album. They will browse the /StoreManager/Edit/id URL (id being the unique id of the album to edit), thus making an HTTP-GET call to the server.

The Controller Edit action method will retrieve the appropriate Album from the database, create a StoreManagerViewModel object to encapsulate it (along with a list of Artists and Genres), and then pass it off to a View template to render the HTML page back to the user. This page will contain a <form> element with textboxes and dropdowns for editing the Album properties.

Once the user updates the Album form values and clicks the Save button, the changes are submitted via an HTTP-POST call back to /StoreManager/Edit/id. Although the URL remains the same as in the last call, ASP.NET MVC identifies that this time it is an HTTP-POST and therefore executes a different Edit action method (one decorated with [HttpPost]).

Task 1 – Creating the StoreManagerViewModel

In order to build and manage the intended Edit form, you will first need to pass to the View template an object with the following:

  1. An Album object that represents the current Album being edited
  2. A List of all Genres to populate the Genre dropdown list
  3. A List of all Artists to populate the Artist dropdown list

In this task, you will create a new StoreManagerViewModel class to help manage all of the above data. This class will be used within both Edit and Create action methods.

  1. Start Microsoft Visual Web Developer 2010 Express from Start | All Programs | Microsoft Visual Studio 2010 Express | Microsoft Visual Web Developer 2010 Express.
  2. In the File menu, choose Open Project. In the Open Project dialog, browse to Source\Ex03-CreatingTheEditView\Begin, select MvcMusicStore.sln and click Open.
  3. Create the StoreManagerViewModel class. To do this, right-click on the ViewModels folder, select Add and then Class.
  4. Change the name to StoreManagerViewModel.[cs|vb] and click Add.

    Figure 1

    Creating StoreManagerViewModel class – C#

    Figure 13

    Creating StoreManagerViewModel class - VB

  5. If you are using C#, add the following using directives:

    (Code Snippet – ASP.NET MVC 3 Helpers and Forms and Validation – Ex3 using System.Web.Mvc and MvcMusicStore.Models – CSharp)

    C#

    using System;
    FakePre-acd9b9eabfe64e4782d728946a77d9f7-a2271b42ea02400592653aefb2e25615FakePre-ea076229e13448dc98fc32f249265662-06e9fa67169d40998cca083b805c0269FakePre-335cbdb215e24037af2ee87b866980df-24182c610e784cbea3b2a120c0501ddeusing System.Web.Mvc; using MvcMusicStore.Models;

  6. Add the Album, Artists and Genres properties.

    (Code Snippet – ASP.NET MVC 3 Helpers and Forms and Validation – Ex3 StoreManagerViewModel properties– CSharp)

    C#

        public class StoreManagerViewModel
    FakePre-3a2eca9439514b4d8633ead9a6a7ed60-73d16e9f95734f448e2acb70732c0763 public Album Album { get; set; } public SelectList Artists { get; set; } public SelectList Genres { get; set; }FakePre-43ce351bd20f456ea1c0d6795a84c338-043c9fa76cac4eb88f715addb217b422

    (Code Snippet – ASP.NET MVC 3 Helpers and Forms and Validation – Ex3 StoreManagerViewModel properties– VB)

    Visual Basic

    Public Class StoreManagerViewModel
    FakePre-7f7a6fcbbfee4a0a90c89b55321a97dd-afc76e9ba46d474da99df21058c76ebf Public Property Album As Album Public Property Artists As SelectList Public Property Genres As SelectListFakePre-a4d97e160ec44c3593942b9e6248b32f-901c2723ed4d4655b7c1f94cee9c50d5FakePre-c1d52b3e16d94a5f8fe610718f263017-2b0f8a78a3af40d18eb9f8a039df03ff

    Note:
    You are using System.Web.MvcSelectList for Artists and Genres instead of the System.Collections.Generic List.

    SelectList is a cleaner way to populate HTML dropdowns and manage things like current selection. Instantiating and later setting up these ViewModel objects in the controller action will make the Edit form scenario cleaner.

Task 2 – Implementing the HTTP-GET Edit Action Method

In this task, you will implement the HTTP-GET version of the Edit action method to retrieve the appropriate Album from the database, as well as a list of all Genres and Artists. It will package this data up into the StoreManagerViewModel object defined in the last step, which will then be passed to a View template to render the response with.

  1. Open StoreManagerController class. To do this, expand the Controllers folder and double-click StoreManagerController.[cs|vb].
  2. If you are using C#, add a using directive to MvcMusicStore.ViewModels. In order for the code to compile correctly, add the following using directive:

    (Code Snippet – ASP.NET MVC 3 Helpers and Forms and Validation – Ex3 using MvcMusicStore.ViewModels – CSharp)

    C#

    using MvcMusicStore.Models;
    using MvcMusicStore.ViewModels;

  3. Replace the HTTP-GET Edit action method with the following code to retrieve the appropriate Album as well as the Genres and Artists lists.

    (Code Snippet – ASP.NET MVC 3 Helpers and Forms and Validation – Ex3 StoreManagerController HTTP-GET Edit action – CSharp)

    C#

            //
    FakePre-9652770e76be46618d9090c5867d66b7-7d43f30857c54235b38f7e6d955f2e5eFakePre-ee01d8f39933414089e4567f06e53d86-ba272370393b4303994cf06e9035efdcFakePre-c748b5d40e724fcc9f9cf3d6178bb658-8600f161ace14f19bcc1d5994fe4c298FakePre-18ef051d5fe94a1b85e1896e3b5f654b-681bdd5b12b444ee95b520d3b32d31c3 Album album = storeDB.Albums.Single(a => a.AlbumId == id); var viewModel = new StoreManagerViewModel() { Album = album, Genres = new SelectList(storeDB.Genres.ToList(), "GenreId", "Name", album.GenreId), Artists = new SelectList(storeDB.Artists.ToList(), "ArtistId", "Name", album.ArtistId) }; return View(viewModel);FakePre-a85a19e3298d42c6800f47408c3aa24f-78570597b8c246a3b6636c3c654f5bf1FakePre-c194ba2b5d5741ddbc0d46c11eb43450-f4e3d64992984d9d8b8a1d12ae7db4f5FakePre-fcd52eff0328423aa730927d2a272ef4-c3321c6da2ab4dac84dc4727e119ea6e

    (Code Snippet – ASP.NET MVC 3 Helpers and Forms and Validation – Ex3 StoreManagerController HTTP-GET Edit action – VB)

    Visual Basic

        '
    FakePre-af8e543fc0fd4205bd189dc85c7e143c-1c686a850bc0493181be0352c72894edFakePre-010dcbfea9e642c5ba9f1fd04987ff95-7534ce7006604d78876934aac98fd5d7 Function Edit(ByVal id As Integer) As ActionResult Dim album As Album = storeDB.Albums.Single(Function(a) a.AlbumId = id) Dim viewModel = New StoreManagerViewModel With {.Album = album, .Genres = New SelectList(storeDB.Genres.ToList(), "GenreId", "Name", album.GenreId), .Artists = New SelectList(storeDB.Artists.ToList(), "ArtistId", "Name", album.ArtistId)} Return View(viewModel) FakePre-cc31480ecad547deb1133b2f27edbfae-035754c5b078406884397560dcd6873cFakePre-9faab25d806d4b77bf147af5ad0a2ed4-f2038441abc74e4f80cec4b572725187

Task 3 – Creating the Edit View

In this task, you will create an Edit View template that will later display the album properties.

  1. Before creating the new View template, you should build the project so that the Add View Dialog knows about the class to use. Build the project by selecting the Debug menu item and then Build MvcMusicStore.

    Figure 14

    Building the project

  2. Create the Edit View. To do this, right-click inside the Edit action method and select Add View.
  3. In the Add View dialog, verify that the View Name is Edit. Check the Create a strongly-typed view checkbox and select StoreManagerViewModel (MvcMusicStore.ViewModels) from the View data class drop-down. Select Edit from the View content drop-down. Leave the other fields with their default value and then click Add.

    Figure 15

    Adding an Edit View

  4. The generated Edit View template doesn’t include any fields because none of the properties in the StoreManagerViewModel are simple types like strings and integers.

    Figure 2

    Edit View without fields – C#

    Figure 17

    Edit View without fields - VB

Task 4 – Customizing the Edit View

In this task, you will change the default View template to display the Album properties.

  1. Add an Html.EditorFor() helper to render a default HTML editing form for the Album.

    HTML(C#)

    <legend>Edit Album</legend> <%: Html.EditorFor(model => model.Album, new { Artists = Model.Artists, Genres = Model.Genres })%>
    FakePre-f75c556683fb418da66ca62f78d5ab7e-125a4fba03154f85aa67312d7255a289FakePre-2630cc18f6b3452386d17ad1d13a2144-fe7bec60065c47009386bba9ca968a85FakePre-4bf2b5fe4c404899803c8733fe041f72-c5e99bb5daee492b8cf6dd60324b4639FakePre-aa75dd1103f745be98237d2a3e3d5a07-fdbcdbe298b04fdba6548f7b04ee04e8
    

    HTML(Visual Basic)

    <legend>Edit Album</legend> <%: Html.EditorFor(Function(model) model.Album, New With {Key .Artists = Model.Artists, Key .Genres = Model.Genres })%>
    FakePre-e2d5b57938b14f7d8a19ead350a8fae2-f8f00624ee0742a999321bdf11deb02cFakePre-7475cd7b4f5447f0b47e369868195cc5-826808a54c7d4947b3dde047f60f9235FakePre-8469bd0911b140b5afbf366e9e9f6999-63e43b513e9943d4af0ae62ad61ad4d1FakePre-3e47b634567540d28734c0e12d535f0a-887b6022e996454bbf1baa373cd90887
    

    Note:
    Html.EditorFor() helper will create a form that will enable the edition of its first parameter, in this case an Album. Additionally, you are passing a second parameter which is optional, that contains the list of Artists and Genres. This will be used later on.

Task 5 – Running the Application

In this task, you will test that the StoreManagerEdit View page displays the properties’ values for the album passed as parameter.

  1. Press F5 to run the Application.
  2. The project starts in the Home page. Change the URL to /StoreManager/Edit/388 to verify that the properties’ values for the album passed are displayed.

    Figure 18

    Browsing Album’s Edit view

Task 6 – Creating a Shared Album Editor Template

Since the exact same form fields for Album Edit will be needed to handle the Album Create case, in this task you will create a Shared Album Editor template that will take care of both cases with the same code.

  1. Close the browser if needed, to return to the Visual Studio window. Create a folder inside /Views/Shared folder and name it EditorTemplates.

    Figure 19

    Adding a new folder

  2. Right-click the EditorTemplates folder, select Add and then View.

    Figure 20

    Adding a View template

  3. This will be a Partial View, meaning that it is intended to be displayed inside another view. In the Add View dialog, change the Name to Album. Check the Create a partial view (.ascx) checkbox and the Create a strongly-typed view checkbox. Select Album (MvcMusicStore. Models) from the View data class drop-down and select Edit from the View content drop-down. Leave the other fields with their default value and then click Add.

    Figure 21

    Adding a Partial View

Task 7 – Implementing drop-downs on the Album Editor Template

In this task, you will add drop-downs to the View template created in the last task, so that the user can select from a list of Artists and Genres.

  1. Replace Album.ascx Partial View code with the following:

    HTML(C#)

    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MvcMusicStore.Models.Album>" %> <p> <%: Html.LabelFor(model => model.Title) %> <%: Html.TextBoxFor(model => model.Title) %> <%: Html.ValidationMessageFor(model => model.Title) %> </p> <p> <%: Html.LabelFor(model => model.Price) %> <%: Html.TextBoxFor(model => model.Price) %> <%: Html.ValidationMessageFor(model => model.Price) %> </p> <p> <%: Html.LabelFor(model => model.AlbumArtUrl) %> <%: Html.TextBoxFor(model => model.AlbumArtUrl) %> <%: Html.ValidationMessageFor(model => model.AlbumArtUrl) %> </p> <p> <%: Html.LabelFor(model => model.Artist) %> <%: Html.DropDownList("ArtistId", (SelectList) ViewData["Artists"]) %> </p> <p> <%: Html.LabelFor(model => model.Genre) %> <%: Html.DropDownList("GenreId", (SelectList) ViewData["Genres"]) %> </p>

    HTML(Visual Basic)

    <%@ Page Title="" Language="VB" MasterPageFile="~/Views/Shared/Site.Master" 
    FakePre-c1dbeb3f042a4d0dad410835dd11ce59-beec582e760d4bd1a581188797f9cb55FakePre-5c36dbe126434a7a86351278bbb1f566-c404d7a1a64d4286af7a565721918ddeFakePre-5e6d4672d7f14fbf9d8f0603220664b9-0c338057907b4c0588416b6f4480c12dFakePre-d85144ba7d0d43f4832c1a21c0090ba1-62101156ab664cfd943d7fd441eca4f3FakePre-ea14b05e5b974a1ebfd85e04632095a6-89c4f87a3f81487486f5493fed87c726FakePre-cd9d2d2ef62b464eb1a4f10d81e6e59e-65e1d2958005401195d26696528e6203FakePre-12ad36d7d8eb4600806c1b9e95979407-188bfe60c9c64ceaaea2619df362b96eFakePre-821acaf2722e4114b022fec83f35a1d0-41c86ff41c40484c8c87a8c987d3f02fFakePre-af9b5d779e354be2967b38287df8e8ba-aecc84ba23824cdab88f75814910933eFakePre-e84991a1233441969aa6563b8cb29092-7c2c3f705c904b0a90485cca882c96f2FakePre-f8b0ff9962f24e0f94c17f353916eaa3-d728a885eb224bdb8e79ac1e3e43250cFakePre-e273e63cda8743ceb6444c76fdefcc47-296f741c6b46454bbc8146cb24c0aec3FakePre-8e9befacedcb4c0aa3afadeabcb6d630-a717a41694fc4e27a2960dbe1de58d7eFakePre-85913a46044b428091835172759625bb-79eb70151ade468c9d3021f9b6f084dbFakePre-7a0b8e09f7d44b548b636ad32472845a-dc31b70274ab4a4fbcb5f4aaf949e6ffFakePre-584f6a7188024db5b079491473b0103b-2d6553f3b5b540ae938e48b54e4b6c60FakePre-3118698b761948eaaa07cd2957c812b2-d0fe88496dc94bb6b35e9438e9436719FakePre-f83d7974361745e5b5626452355395b5-f11c5a40b31a464dbe911220d5129564FakePre-4a89cf6f193c453d8b61ca91c159ccd0-45ad8ef8d5164659942034f5ff7546f5FakePre-171f3d0b7b1e4ee1b60c429d8678d7c6-a9d266ae657c4345b0e52cd3e9e60383FakePre-ebbc99314ff84ed2b973e6116d212361-3a60d482c0bf4023890a4ca02c4b8ab4FakePre-4218f2bc29514d2c8d147bd7e46d5ba4-1cda871a1d4145689fbe39be680d6c24FakePre-90eb75283842490ea7dc88c902e84599-39fe30e441f94a82b09f4872aa967c3aFakePre-05a18f9246a2422985379fa60ee3f558-fcf942a100f44b278f30242d791c331eFakePre-d1b14f516a844df98a3e7df2f96c0d41-37e49dc40c104e7583d0f71d378e7e46

    Note:
    An Html.DropDownList helper has been added to render drop-downs for choosing Artists and Genres. The parameters passed to Html.DropDownList are:

    1. The name of the form field (“ArtistId”)

    2. The SelectList of values for the drop-down. ViewData is actually the object taken from the Html.EditorFor second parameter you included in task 4:

    C#

    <%: Html.EditorFor(model => model.Album,

    new { Artists = Model.Artists, Genres = Model.Genres })%>

    Visual Basic

    <%:Html.EditorFor(Function(model) model.Album,

    New With {Key .Artists = Model.Artists, Key .Genres = Model.Genres})%>

    Html.EditorFor() helper will create a form that will enable the edition of its first parameter, in this case an Album. Additionally, you are passing a second parameter which is optional, that contains the list of Artists and Genres. This will be used later on.

Task 8 – Running the Application

In this task, you will test that the StoreManagerEdit View page displays drop-downs instead of Artist and Genre ID text fields.

  1. Press F5 to run the Application.
  2. The project starts in the Home page. Change the URL to /StoreManager/Edit/388 to verify that it displays drop-downs instead of Artist and Genre ID text fields.

    Figure 22

    Browsing Album’s Edit view, this time with dropdowns

Task 9 – Implementing the HTTP-POST Edit action method

Now that the Edit View displays as expected, you need to implement the HTTP-POST Edit Action method to save the changes made to the Album.

  1. Close the browser if needed, to return to the Visual Studio window. Open StoreManagerController from the Controllers folder.
  2. Replace HTTP-POST Edit action method code with the following (note that the method that must be replaced is overloaded version that receives two parameters):

    (Code Snippet – ASP.NET MVC 3 Helpers and Forms and Validation – Ex3 StoreManagerController HTTP-POST Edit action – CSharp)

    C#

            //
    FakePre-79a94994b743411998b067e4a5ea6a49-f93ffa6a66d84e76ab5df1ddcff22f4aFakePre-4bf36c36563c4e33b3b289f1a78f193b-9acee02332c44a3a8e1c36adc798c77dFakePre-6c039cd992a74dfba941c00c84d9910c-3901aa1875194ed79f2034737ed24be5FakePre-675487c567dd4ee3aafbc3bf35026ee1-212b2b302d11448d9f0aa652c4a438cbFakePre-7bb1c38f60ef4b3baaecf333568554d9-43ed7798dc18424b9ff3ca5bf235f821 var album = storeDB.Albums.Single(a => a.AlbumId == id); try { // Save Album UpdateModel(album, "Album"); storeDB.SaveChanges(); return RedirectToAction("Index"); } catch { // Error occurred - so redisplay the form var viewModel = new StoreManagerViewModel() { Album = album, Genres = new SelectList(storeDB.Genres.ToList(), "GenreId", "Name", album.GenreId), Artists = new SelectList(storeDB.Artists.ToList(), "ArtistId", "Name", album.ArtistId) }; return View(viewModel); }FakePre-cb15c889266348de8edfe3d6172d1971-b59a760d1b9943989aba7cfa03cfeb82FakePre-f23b903fe64f49c19b3286a654b31bea-ae5e8b260c644ce88bc4939b82c3c1f4FakePre-523506cdb3e7421cbc1b16e0812ed6fc-9e2031deb9694a57ac8521195a935205FakePre-4d5bea67b3034be7b452280689a5ace6-3ce5e774f80c4e3b9fc72135306502c5FakePre-ef1d9c81815d418ca2984a1c23bf8dd0-c5e96c8fe228466aa371b0cc347ecf0a

    (Code Snippet – ASP.NET MVC 3 Helpers and Forms and Validation – Ex3 StoreManagerController HTTP-POST Edit action – VB)

    Visual Basic

        '
    FakePre-3e83ee6560fd41769a638ac9ef4156dd-9bf700d47f0044bdbe6bbcfd25a798a8FakePre-fd353301929343aa92210c1e4f9d71db-2fd4568da2364183b12f89f525948262FakePre-a4de8f77469b4069a469120186118023-144247e824674d2da4fddd23889c9c74FakePre-5588430518874a42a3e1b99e84ab55d6-e097a8ab31d647258152a3f3ddfd07c3FakePre-23796046625f476ab61d816ea08221ec-27b363e82f784448a71acbaf08a29446FakePre-f70474717f354d96b7f075377b59e335-bf3fe0ed9a6a4cb1bb120dbcd1387097FakePre-309b7bfbcaf746a9beeb930768b73be6-705f087d1f0b4d7e880ed7e0bea9dd5a Dim album = storeDB.Albums.Single(Function(a) a.AlbumId = id) Try 'Save Album UpdateModel(album, "Album") storeDB.SaveChanges() Return RedirectToAction("Index") Catch 'Error occurred - so redisplay the form Dim viewModel = New StoreManagerViewModel With {.Album = album, .Genres = New SelectList(storeDB.Genres.ToList(), "GenreId", "Name", album.GenreId), .Artists = New SelectList(storeDB.Artists.ToList(), "ArtistId", "Name", album.ArtistId)} Return View(viewModel) End TryFakePre-18c670c1f3de4147b634b709e7dbaaad-81231e5cd6d3437e9c4a665d6ac5e660FakePre-1daf31ccca084aea88b63d38da8cc2a5-c8b9717a3d2b41bfa5db63924a0c9693FakePre-29273d28a11140c7ac360df56c73f2c5-3c170c9d03ce484f903c3c19500d4d20FakePre-844d57a7b9b248f0bad3f48a8568a374-b80fc26e49d845c49b343bb00f6379acFakePre-07acb58cb88b4de395f11d0002ec701e-3b1fe2bc5a214b4b822cb05b3fd20548FakePre-d627639ea62a415baf9f6aadf1e7b17a-690e27cfda27476184e80696dfcf4176

    Note:
    This method will be executed when the user clicks the Save button of the View and performs an HTTP-POST of the form values back to the server to persist them in the database. The decorator [HttpPost] indicates that the method should be used for those HTTP-POST scenarios.

    The method takes an id (read from the route parameter values) and a FormCollection (read from the HTML Form).

    The method will perform three steps:

    1. Load the existing album object from the database with the id passed as parameter

    2. Try to update the album using the values posted from the client, using the Controller’s built-in UpdateModel method. The UpdateModel method actually relies on the ModelBinder (MVC 2.0) to identify that you are actually updating a StoreManagerViewModel instance. Since that ViewModel holds an Album object and also 2 SelectLists for Artists and Genres, the key “Album” you are including as UpdateModel’s second parameter, refers to the need of updating the “Album” property of the Model.

    3. Display results back to the user – either by redisplaying the form in case of an error, or by redirecting back to the list of albums in case of a successful update

Task 10 – Running the Application

In this task, you will test that the StoreManagerEdit View page actually saves the updated Album data in the database.

  1. Press F5 to run the Application.
  2. The project starts in the Home page. Change the URL to /StoreManager/Edit/388. Change the Album title to Greatest Hits Vol. 1 and click on Save. Verify that album’s title actually changed in the list of albums.

    Figure 23

    Updating an Album

Next Step

Exercise 4: Adding a Create View