1
votes

I looked through various tutorials, but I feel very confused on how I want to go about executing what I have in mind and want some help to clarify my thoughts.

I will have a razor view page called Profile; on that profile page I have four different sections:

  1. Password change
  2. Setup password
  3. User name
  4. Biography.

I was thinking of creating each of the four sections as a partial section and each section will have text boxes and a save button that will allow the user to add or alter information.

@model Projects.Models.PasswordModel
@{
    ViewBag.Title = "Profile Account";
}

<hgroup class="title">
    <h1>@ViewBag.Title.</h1>
</hgroup>

<p class="message-success">@ViewBag.StatusMessage</p>


<div id="wrap">
    <div id="right">
        @if (ViewBag.HasLocalPassword)
        {
            @Html.Partial("_ChangePasswordPartial")
        }
        else
        { 
            @Html.Partial("_SetPasswordPartial")
        }
    </div>

    <div id="left">
        @Html.Partial("_UserNamePartial")
        @Html.Partial("_BiographyPartial")
    </div>
</div>

How can I properly set up the main view page and have the four sections properly displayed and functional? I got them to be displayed, but when I try to save a change I made to the username I would get an error for a different model--say the biography model. I feel like they are being connected when they shouldn't. I am really looking for a clear tutorial of how to go about this and hopefully I will be able to make one after I figure this out.

This is my username partial

@model Project.Models.UsernameModel

@using (Html.BeginForm("_UsernamePartial", "Account")) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary()

       <p>Username</p>
       @Html.TextBoxFor(m=>m.Username)

    <button class="btn btn-small" type="submit" value="Save Username">Save</button>
}

My controller

GET:

public ActionResult _UsernamePartial()
        {
            var usernameModel = new UsernameModel();
            using (var db = new DataContext())
            {
                usernameModel.Nickname = (from u in db.Users
                                              where u.ID == WebSecurity.CurrentUserId
                                              select u.Username).FirstOrDefault();
            }
            return View(usernameModel);
        }

POST:

[HttpPost]
        public ActionResult _UsernamePartial(UsernameModel usernameModel, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                using (var db = new DataContext())
                {
                     User user = db.Users.FirstOrDefault(m => m.ID == WebSecurity.CurrentUserId);
                     user.Username = usernameModel.Username;
                     db.SaveChanges();
                 }
                return RedirectToAction("_UsernamePartial");
            }
            return View(returnUrl);
        }

Your help is greatly appreciated.

1
Do you have different models for each section? Your view is strongly typed to PasswordModel, which appears separate from the biography model you mention. If you're going to do this you'll need a model composed of the models for each page section. - JeffB
@JeffB something like this maybe: public class AccountManageModel { public LocalPasswordModel PasswordModel { get; set; } public NicknameModel UsernameModel { get; set; } public ProgramNameModel biographyModel { get; set; } } and each one will be its own class? - 072et
Yeah, something like that. Then you could pass each one into the corresponding partial view. - JeffB

1 Answers

1
votes

You need to make sure your views are typed to the right model. Your view currently is typed to the PasswordModel model, which appears to be one section of your page. If you create a model composed of models for each section, it will make this easier:

class ProfileModel {
    PasswordModel Password { get; set; }
    BiographyModel Biography { get; set; }
    ...
}

You would then set your Profile view to be typed to ProfileModel. Then you can pass each model to the partials:

@Html.Partial("_BiographyPartial",Model.Biography)

And an example _BiographyPartial would look like:

@model Projects.Models.BiographyModel
...
<h1>@Model.SomeBiographyProperty</h2>

You should be careful to check that your validation, assuming you have some, is working correctly with this set up.

Alternatively, you could put all of your data into one flat model and pass the whole model to each partial view.

EDIT: Partial views aren't backed by controllers and actions, they're simply views that are rendered using the data you pass to them from the calling view. What you're trying to do right now is render the _UsernamePartial action. If you want to do that you can try using Action instead of Partial:

<div id="left">
    @Html.Action("_UserNamePartial")
    ...
</div>

And render that action as a partial view:

public ActionResult _UsernamePartial()
{
    var usernameModel = new UsernameModel();
    using (var db = new DataContext())
    {
        usernameModel.Nickname = (from u in db.Users
                                  where u.ID == WebSecurity.CurrentUserId
                                  select u.Username).FirstOrDefault();
    }
    return PartialView(usernameModel);
}