views:

278

answers:

1

I am fairly new to the MVC Framework and have spent the last few days/nights working through the tutorials. I have a loosely coupled design with Services and Providers and am using the Entity Framework. I am using all the latest software, Visual Studio 2008, .Net 3.5 Framework, MVC, Entity Framework.

I'm trying to create a view Artist/Create where the user has to input all the Artist and all the Contact fields. Here's what I have:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using System.Text.RegularExpressions;
using Website.Models;
using Website.Models.Validation;
using Website.Models.Services;

namespace Website.Controllers
{
public class ArtistController : Controller
{
    private IArtistService _service;
    private ModelStateWrapper _msw;

    public ArtistController()
    {
        _msw = new ModelStateWrapper(this.ModelState);
        _service = new ArtistService(_msw);
    }

    public ArtistController(IArtistService service)
    {
        _service = service;
    }

    //
    // GET: /Artist/

    public ActionResult Index()
    {
        return View(_service.ListArtists());
    }

    public ActionResult Create()
    {
        ViewData["Countries"] = new SelectList(new CountryService(_msw).ListCountries().OrderBy(c => c.Name),"ID","Name");
        return View();
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Create([Bind(Exclude = "Id")] Artist artist)
    {
        ViewData["Countries"] = new SelectList(new CountryService(_msw).ListCountries().OrderBy(c => c.Name), "ID", "Name");
        if (_service.CreateArtist(artist))
            return RedirectToAction("Index");
        return View("Create");
    }

    public ActionResult Edit(string name)
    {
        return View(_service.GetArtist(name));
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Edit(Artist artistToEdit)
    {
        if (_service.EditArtist(artistToEdit))
            return RedirectToAction("Index");
        return View();
    }

    public ActionResult Delete(string name)
    {
        return View(_service.GetArtist(name));
    }

    [AcceptVerbs(HttpVerbs.Post)]
    public ActionResult Delete(Artist artistToDelete)
    {
        if (_service.DeleteArtist(artistToDelete))
            return RedirectToAction("Index");
        return View();
    }
}
}

And this is the View Artist/Create.aspx

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
   <asp:Content ID="Content3" ContentPlaceHolderID="HeadContent" runat="server">
    <title>Artist</title>
    <link href="../../Content/ui-lightness/jquery-ui-1.7.1.custom.css" rel="stylesheet" type="text/css" media="screen" />
    <script src="../../Scripts/jquery-1.3.2.js" type="text/javascript"></script>
    <script src="../../Scripts/ui.core.js" type="text/javascript"></script>
    <script src="../../Scripts/ui.datepicker.js" type="text/javascript"></script>
    <script src="../../Scripts/jquery-ui-1.7.1.custom.min.js" type="text/javascript"></script>
    <script src="../../Scripts/ui.qtips.js" type="text/javascript"></script>
   </asp:Content>
   <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Create Artist</h2>
<%= Html.ValidationSummary() %>

<% using (Html.BeginForm()) {%>

    <fieldset class="fields">
        <legend>Create New Artist</legend>
        <p>
            <label for="Name">Name:</label>
            <%= Html.TextBox("Name", "", new { watermark = "Name", title = "Please enter your Artist name." })%>
            <%= Html.ValidationMessage("Name", "*") %>
        </p>

        <fieldset class="fields">
            <legend>Contact Information</legend>
            <p>
                <label for="FirstName">First Name:</label>
                <%= Html.TextBox("FirstName", "", new { watermark = "FirstName", title = "Please enter your first name." }) %>
                <%= Html.ValidationMessage("FirstName", "*") %>
            </p>
            <p>
                <label for="LastName">Last Name:</label>
                <%= Html.TextBox("LastName", "", new { watermark = "Lastname", title = "Please enter your last name." })%>
                <%= Html.ValidationMessage("LastName", "*") %>
            </p>
            <p>
                <label for="Phone">Phone:</label>
                <%= Html.TextBox("Phone", "", new { watermark = "+12 123 123456", title = "Please enter your phone number." })%>
                <%= Html.ValidationMessage("Phone", "*") %>
            </p>
            <p>
                <label for="Email">Email:</label>
                <%= Html.TextBox("Email", "", new { watermark = "[email protected]", title = "Please enter your email address." })%>
                <%= Html.ValidationMessage("Email", "*") %>
            </p>
            <p>
                <label for="BirthDate">Date of Birth:</label> 
                <%= Html.TextBox("Birthdate", "", new { Class = "date-pick", watermark = "mm/dd/yyyy", title = "Please select your date of birth." })%> 
                <%= Html.ValidationMessage("Birthdate", "*") %>
            </p>
            <p>
                <label for="AddressLine1">Address:</label>
                <%= Html.TextBox("AddressLine1", "", new { watermark = "", title = "Please enter your address." })%>
                <%= Html.ValidationMessage("AddressLine1", "*") %>
            </p>
            <p>
                <label for="AddressLine2"></label>
                <%= Html.TextBox("AddressLine2", "", new { watermark = "First", title = "Optional additional addressline." })%>
                <%= Html.ValidationMessage("AddressLine2", "*") %>
            </p>
            <p>
                <label for="Country">Country:</label>
                <%= Html.DropDownList("City", (IEnumerable<SelectListItem>)ViewData["Countries"],string.Empty, new { watermark = "First", title = "Please enter your email address." })%>
                <%= Html.ValidationMessage("City", "*") %>
            </p>
            <p>
                <label for="City">City:</label>
                <%= Html.TextBox("City", "", new { watermark = "", title = "Please specify your City.", @class="tooltip" })%>
                <%= Html.ValidationMessage("City", "*") %>
            </p>
            <p>
                <label for="ZipCode">ZipCode:</label>
                <%= Html.TextBox("ZipCode", "", new { watermark = "", title = "Please specify your Zipcode." })%>
                <%= Html.ValidationMessage("ZipCode", "*") %>
            </p>
            <fieldset class="fields">
                <legend>Sex/Gender</legend>
                <label for="SexMale">Male</label>
                <%= Html.RadioButton("Sex", "Male", new { @id = "Sex.Male" })%>
                <label for="SexFemale">Female</label>
                <%= Html.RadioButton("Sex", "Female", new { @id = "Sex.Female" })%>
                <%= Html.ValidationMessage("Sex", "*") %>
            </fieldset>

        </fieldset>
        <p class="submit">
            <input type="submit" value="Create" />
        </p>
    </fieldset>

<% } %>
<!-- jquery plugins -->
<script type="text/javascript">
    $(function() {
       $('.date-pick').datepicker({
           changeMonth: true,
           changeYear: true,
           yearRange: '1900:' + (new Date()).getFullYear()
       });
       $('.tooltip').qtip({ content: 'this is a nice tooltip', position: 'center' });
   });
</script>
<!-- /jquery plugins -->
</asp:Content>

I can open this page fine and enter all the data. Here's is where I try to save the Artist using the ArtistService (this is where it goed wrong) :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text.RegularExpressions;
using Website.Models.Repositories;
using Website.Models.Validation;

namespace Website.Models.Services
{
    public class ArtistService : IArtistService
    {
        private IValidationDictionary _validationDictionary;
        private IArtistRepository _repository;

        public ArtistService(IValidationDictionary validationDictionary) 
            : this(validationDictionary, new EntityArtistRepository()){}

        public ArtistService(IValidationDictionary validationDictionary, IArtistRepository repository)
        {
            _validationDictionary = validationDictionary;
            _repository = repository;
        }

        public bool ValidateArtist(Artist artist)
        {
            ContactService contactService = new ContactService(_validationDictionary);
            if (contactService.ValidateContact(artist.Contact))
                _validationDictionary.AddError("Contact", "Invalid Contact information.");

            if (_validationDictionary.IsValid)
            {
                CountryService countryService = new CountryService(_validationDictionary);
                if (artist.Contact.Country != null && countryService.ValidateCountry(artist.Contact.Country))
                    _validationDictionary.AddError("Country", "Country is required.");
            }

            if (artist.Name == null || artist.Name.Trim().Length == 0) {
                _validationDictionary.AddError("Name", "Artist name is required.");
            }

            return _validationDictionary.IsValid;
        }

        #region IArtistService Members

        public bool CreateArtist(Artist artist)
        {
            // Validation logic
            if (!ValidateArtist(artist))
                return false;

            // Database logic
            try
            {
                _repository.CreateArtist(artist);
            }
            catch
            {
                return false;
            }
            return true;
        }

        public bool EditArtist(Artist artist)
        {
            // Validation logic
            if (!ValidateArtist(artist))
                return false;

            // Database logic
            try
            {
                _repository.EditArtist(artist);
            }
            catch
            {
                return false;
            }
            return true;
        }

        public Artist GetArtist(int Id)
        {
            return _repository.GetArtist(Id);
        }

        public bool DeleteArtist(Artist artist)
        {
            try
            {
                _repository.DeleteArtist(artist);
            }
            catch
            {
                return false;
            }
            return true;
        }

        public IEnumerable<Artist> ListArtists()
        {
            return _repository.ListArtists();
        }

        public Artist GetArtist(string name)
        {
            return _repository.GetArtist(name);
        }

        #endregion
    }
}

Can anyone tell me why everytime, in ValidateArtist, the Contact property of the Artist Entity appears to be empty? How do I tell MVC that it should link the contact input fields to the Contact property of the Artist Entity?

I hope it is ok that I've pasted all the code here, seems like a lot...

Thanks, Peter

+1  A: 

You actually have two models that you are creating. Try prepending the Contact designator to the Contact fields.

      <p>
            <label for="Contact_Phone">Phone:</label>
            <%= Html.TextBox("Contact.Phone", "", new { watermark = "+12 123 123456", title = "Please enter your phone number." })%>
            <%= Html.ValidationMessage("Contact.Phone", "*") %>
     </p>

Then if it doesn't populate the Contact field in your action, try adding a Contact parameter to the action method and setting the Contact property on artist from it.

public ActionResult Create([Bind(Exclude = "Id")] Artist artist,
                           [Bind(Prefix = "Contact")] Contact contact )
{
    artist.Contact = contact;
    ...
}
tvanfosson
Thanks for the clear explanation, it seems to work great like this. I think I understand most of it now :)
Peter