views:

28

answers:

1

Hi guys, i'm having issues with implementing a ViewModel class which acts as a wrapper class around a Model class called "User" generated by L2SQL. In short, I have two instances when i have to validate against the L2SQL model. One when the user first signs up, and the second when the user logs in and edits only part of his account data.

The initial "problem" was when trying to edit & validate only some the account details against the original L2SQL model from a View which only displays the few (e.g FirstName, LastName, Email), the missing ones (e.g. Password) would flair up when validation was run. The Password settings will have its own View.

I was advised here on StackOverflow that adding a wrapping ViewModel class would be the best solution. So I did, implemented below:

ViewModel code:

[Bind]
public class AccountEdit 
{ 
    public User UserAccount { get; set; } 

    [Required(ErrorMessage = "First name required"), StringLength(20, MinimumLength = 3, ErrorMessage = "Must be between 3 and 20 characters")]   
    public string FirstName  { get { return UserAccount.FirstName; } set { UserAccount.FirstName = value; } }

    [Required(ErrorMessage = "Last name required"), StringLength(20, MinimumLength = 3, ErrorMessage = "Must be between 3 and 20 characters")]
    public string LastName { get { return UserAccount.LastName; } set { UserAccount.LastName = value; } }

    [Required(ErrorMessage = "Email address required"), RegularExpression("^[a-z0-9_\\+-]+(\\.[a-z0-9_\\+-]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*\\.([a-z]{2,4})$", ErrorMessage = "Must be a valid email address")]
    public string Email { get { return UserAccount.Email; } set { UserAccount.Email = value; } }
}

Controller code:

//
// GET /User/Account
public ActionResult Account()
{
    string cookieUser = User.Identity.Name;
    User user = userRepository.GetUserByEmail(cookieUser);
    return View(user);
}

// POST /User/Account
[HttpPost]
public ActionResult Account(AccountEdit model)
{                
    if (ModelState.IsValid)
    {
        model.LastUpdated = DateTime.Now; 
        userRepository.Save();
    }
    return View(model);
}

Veiw code:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/User.Master" Inherits="System.Web.Mvc.ViewPage<Digitalent.Models.User>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Account settings
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

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

    <%= Html.ValidationSummary("Oops! Please correct the errors and try again!") %>

        <p>
            <label for="FirstName">First name:</label>
            <%: Html.TextBoxFor(model => model.FirstName, new { @class = "textfield" })%> 
            <%: Html.ValidationMessageFor(model => model.FirstName) %>
        </p>

        <p>
            <label for="LastName">Last name:</label>
            <%: Html.TextBoxFor(model => model.LastName, new { @class = "textfield" })%> 
            <%: Html.ValidationMessageFor(model => model.LastName) %>
        </p>

        <p>
            <label for="Email">Email address:</label>
            <%: Html.TextBoxFor(model => model.Email, new { @class = "textfield" })%> 
            <%: Html.ValidationMessageFor(model => model.Email) %>
        </p>

        <p>
            Email newsletter: <%= Html.CheckBoxFor(model => model.EmailNewsletter) %>
            <label for="EmailNewsletter">Keep me posted with latest Digitalent happenings.</label>
        </p>


        <p>
            <input type="submit" value="Save changes" class="button" />
        </p>

        <p><a href="/talent/password">Change your password settings</a></p>

<% } %>

But now when i tried to run the app i get an error when it runs the validation:

'Object reference not set to an instance of an object.'

On the line below in my ViewModel:

'public string FirstName { get { return UserAccount.FirstName; } set { UserAccount.FirstName = value; } }'

Where am I going wrong or can anyone else tell me a better recommended approach as i'm a novice. Help please!

A: 

Change your view from:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/User.Master" 
    Inherits="System.Web.Mvc.ViewPage<Digitalent.Models.User>" %>

to:

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/User.Master" 
    Inherits="System.Web.Mvc.ViewPage<Digitalent.Models.AccountEdit>" %>
RedFilter
I get this error if i do that: "The model item passed into the dictionary is of type 'Digitalent.Models.User', but this dictionary requires a model item of type 'Digitalent.Models.AccountEdit'."I need to populate the fields first in the GET View instance using "Digitalent.Models.User".
shahid81
@RedFilter Do i need to change anything in the GET View?
shahid81