1

I'm trying my first adventure using viewmodels, but I got a problem, this is my view model and the models:

ViewModel:

    public class ProfessionalDashboard
    {
        public List<JobOffertModel> AcceptedJobOfferts { get; set; }
        public List<JobOffertModel> NotAcceptedJobOfferts { get; set; }

        public ProfessionalModel Professional { get; set; }
    }

Models:

    public class JobOffertModel
    {
        [Key]
        public int Id { get; set; }

        public ProfessionalModel Professional { get; set; }

        [Required]
        public string Description { get; set; }

        [Required]
        [DefaultValue(false)]
        public bool Accepted { get; set; }

        [Required]
        [DefaultValue(true)]
        public bool Active { get; set; }

        public ICollection<SkillModel> Skills { get; set; }

        [Required]
        [Column(TypeName = "DateTime2")]
        public DateTime JobDate { get; set; }

        public virtual CustomerModel Customer { get; set; }

    }

And ...

public class ProfessionalModel
{
    [Key]
    public int Id { get; set; }

    [Required]
    public string Name { get; set; }

    [Required]
    [Column(TypeName = "DateTime2")]
    public DateTime BirthDate { get; set; }
    public int PhoneNumber { get; set; }
    public string Profession { get; set; }

    public UserAddressModel UserAddress { get; set; }

    [Required]
    public UserAccountModel UserAccount { get; set; }

    public ICollection<SkillModel> Skills { get; set; }

    public ProfessionalModel() {}
}

Here is my View:

@model  TCCApplication.ViewModels.ProfessionalDashboard

@{
    ViewBag.Title = "Dashboard";
}

<div class="row">
    <div class="col-md-5">

        <h2>Minhas tarefas</h2>

        @for (int i = 0; i < Model.AcceptedJobOfferts.Count; i++)
        {

            @Html.HiddenFor(itemModel => Model.AcceptedJobOfferts[i].Id)

            <div class="row">
                <div class="col-md-3">
                    <label>Oferta: </label>
                    @Html.DisplayFor(itemModel => Model.AcceptedJobOfferts[i].Description)
                </div>

                @*<div class="col-md-2">
                    <label>Aceito</label>
                    @Html.DisplayFor(itemModel => Model.AcceptedJobOfferts[i].Accepted)
                </div>*@

                <div class="col-md-5">
                    <label>Data do trabalho</label>
                    @Html.DisplayFor(itemModel => Model.AcceptedJobOfferts[i].JobDate)
                </div>


                @Html.HiddenFor(itemModel => Model.AcceptedJobOfferts[i].Professional.Id)
                @Html.HiddenFor(itemModel => Model.AcceptedJobOfferts[i].Professional.Name)
                @Html.HiddenFor(itemModel => Model.AcceptedJobOfferts[i].Professional.Skills)
                @Html.HiddenFor(itemModel => Model.AcceptedJobOfferts[i].Professional.BirthDate)

                @Html.HiddenFor(itemModel => Model.AcceptedJobOfferts[i].JobDate)
                @Html.HiddenFor(itemModel => Model.AcceptedJobOfferts[i].Active)
                @Html.HiddenFor(itemModel => Model.AcceptedJobOfferts[i].Description)
                @Html.HiddenFor(itemModel => Model.AcceptedJobOfferts[i].Accepted)

            </div>
        }
    </div>
    <div class="col-md-7">
        @using (Html.BeginForm("AcceptJobOfferts","Professional")){

            for (int i = 0; i < Model.NotAcceptedJobOfferts.Count; i++)
            {
                @Html.HiddenFor(itemModel => Model.NotAcceptedJobOfferts[i].Professional)
                @Html.HiddenFor(itemModel => Model.NotAcceptedJobOfferts[i].Professional.Id)
                @Html.HiddenFor(itemModel => Model.NotAcceptedJobOfferts[i].Professional.Name)
                @Html.HiddenFor(itemModel => Model.NotAcceptedJobOfferts[i].Professional.Skills)
                @Html.HiddenFor(itemModel => Model.NotAcceptedJobOfferts[i].Professional.BirthDate)

                @Html.HiddenFor(itemModel => Model.NotAcceptedJobOfferts[i].JobDate)
                @Html.HiddenFor(itemModel => Model.NotAcceptedJobOfferts[i].Active)
                @Html.HiddenFor(itemModel => Model.NotAcceptedJobOfferts[i].Description)
                @Html.HiddenFor(itemModel => Model.NotAcceptedJobOfferts[i].Accepted)        

                @Html.HiddenFor(itemModel => Model.NotAcceptedJobOfferts)

                <h2>Ofertas de trabalho indicadas</h2>

                @Html.HiddenFor(itemModel => Model.NotAcceptedJobOfferts[i].Id)

                <div class="row">
                    <div class="col-md-3">
                        <label>Oferta: </label>
                        @Html.DisplayFor(itemModel => Model.NotAcceptedJobOfferts[i].Description)
                    </div>

                    <div class="col-md-2">
                        <label>Aceito</label>
                        @Html.EditorFor(itemModel => Model.NotAcceptedJobOfferts[i].Accepted)
                    </div>

                    <div class="col-md-5">
                        <label>Data do trabalho</label>
                        @Html.DisplayFor(itemModel => Model.NotAcceptedJobOfferts[i].JobDate)
                    </div>  

                </div>
            }
            <div>
                <input type="submit" value="Aceitar Ofertas" /> <!-- This is the post button -->
            </div>

        }
    </div>

</div>


<div class="row" style="height:50px">




</div>



<div class="row">

    <div class="col-md-12 text-center">
        <div>
            <label>Cliente: </label>

            @Model.Professional.Name
        </div>

        <div>
            <label>Data de nascimento: </label>

            @Model.Professional.BirthDate
        </div>

        <div>
            <label>Telefone: </label>

            @Model.Professional.PhoneNumber
        </div>

        <div>
            <label>Usuário: </label>

            @Model.Professional.UserAccount.Username
        </div>

        <div>
            <label>Profissão: </label>

            @Model.Professional.Profession
        </div>

        <div>
            <label>Bairro: </label>

            @Model.Professional.UserAddress.Neighborhood
        </div>

        <p class="div-to-btn">
            @Html.ActionLink("Alterar informações", "Edit", new { id = @Model.Professional.Id })
        </p>

    </div>
</div>

And this is the method who must to receive the post method:

[HttpPost]
public ActionResult AcceptJobOfferts(ProfessionalDashboard profDash)
{
    initBusinessObjects();

    //foreach (var jo in jobOffertModel)
    //{
    //    jobOffertBusiness.Update(jo);
    //}

    return RedirectToAction("ViewMyTasks", new { professionalId = profDash.Professional.Id});
}

My parameter profDash receives a null Professional Object, a null List and another with zero itens.

How can I make it work?

guisantogui
  • 4,017
  • 9
  • 49
  • 93

2 Answers2

1

All I see in your form are Model.NotAcceptedJobOfferts. If you want to maintain your data you need to add it as a hidden input in your form. Once the view is rendered to the user, your model is lost, the only data available is what has been rendered on the page.

Jonesopolis
  • 25,034
  • 12
  • 68
  • 112
  • I've added this line: `@Html.HiddenFor(itemmodel => Model.NotAcceptedJobOfferts)` to my view, but it keeps sending a zero itens list – guisantogui May 11 '14 at 21:58
  • look [here](http://stackoverflow.com/questions/9385286/html-hiddenfor-does-not-work-on-lists-in-asp-net-mvc#) for some solutions to using hiddenfor with lists – Jonesopolis May 11 '14 at 22:00
  • although honestly you might want to consider a PartialView, that only takes the data needed for the form, and have your controller only receive data modified by the user (`NotAcceptedJobOfferts`) – Jonesopolis May 11 '14 at 22:08
0

You have a plenty of complex types in play. The default model binder is having difficulties in binding the values that are getting posted in the form. Here's something you can do:

  • Check the names of the values in the HTML by doing view source. Make sure they are following [PropertyNameInParentModelClass].[PropertyNameInChildModelClass] convention.For ex: Professional.Name
  • Add a break point in the action method, and inspect the form values.Try looking at HttpContext.Current.Request. Check if all the expected form values are there as expected.
  • Consider simplifying the view models and models a bit by cutting out the things you are not going to need. As you have a complete view of your system(hopefully), you should be able to determine that.
  • Consider using custom model binders. There's plenty of literature on internet on how to have custom model binders. Here's a couple to start with: MSDN article and Code Project Example
Yogiraj
  • 1,952
  • 17
  • 29