Gareth
Gareth

Reputation: 5243

Form Not Posting Data back to Controller

I'm trying to post a form using ASP.Net MVC (C#). When the form is posted, none of the data arrives at the controller. The viewmodel remains in it's initialised state.

You can see below that the form data that is posted (copied from Chrome Developers tools) but when it hits the controller, there's nothing there:

Triage.ClaimNumber:Test-001
Triage.PropertyAgeId:1
Triage.RoomNumber:1
Triage.Rooms[0].RoomHeight:3
Triage.Rooms[0].RoomWidth:3
Triage.Rooms[0].RoomLength:4
Triage.Rooms[0].CleaningRequired:False
Triage.Rooms[0].DryingRequired:False
Triage.Rooms[0].CeilingDamaged:True
Triage.Rooms[0].WallsDamaged:False
Triage.Rooms[0].FloorDamaged:False
Triage.Rooms[0].KitchenDamaged:False
Triage.Rooms[0].BathroomDamaged:False
Triage.Rooms[0].Ceiling.CeilingTypeId:66
Triage.Rooms[0].Ceiling.AmountDamaged:0.10
Triage.Rooms[0].Ceiling.Papered:False

Example

The name conventions are right for the model binding to take automatically, can anyone help me with why the data isn't being posted?

Here's samples of the viewmodels:

Ceiling View Model

public class TriageCeilingViewModel
{
    [DisplayName("Ceiling type")]
    public int CeilingTypeId { get; set; }

    [Required(ErrorMessage = "Please enter the amount of damage to the ceiling")]
    [DisplayName("% Amount damaged")]
    public decimal AmountDamaged { get; set; }

......
}

Triage View Model

public class TriageRoomViewModel
{
    private Repository _data = new Repository();

    public List<CeilingTypeList> CeilingTypes
    {
        get
        {
            return _data.GetCeilingTypes();
        }
    }

    [Required()]
    [DisplayName("Height (m)")]
    public decimal RoomHeight { get; set; }

    [Required(ErrorMessage = "Is the ceiling damaged?")]
    [DisplayName("Ceiling damaged?")]
    public bool CeilingDamaged { get; set; }


    public TriageCeilingViewModel Ceiling = new TriageCeilingViewModel();

    ........
}

Index View Model

public class TriageViewModel
{
    private readonly Repository _data = new Repository();

    public List<PropertyAgeList> PropertyAges
    {
        get
        {
            return _data.GetPropertyAges();
        }
    }

    [Required(ErrorMessage = "Please enter the claim number")]
    [StringLength(12, ErrorMessage = "The claim number must be 12 digits or less")]
    [DisplayName("Claim Number")]
    public string ClaimNumber { get; set; }

    public List<TriageRoomViewModel> Rooms = Enumerable.Range(0, 4).Select(i => new TriageRoomViewModel()).ToList();

    ........
}

TriageIndexViewModel

public class TriageIndexViewModel
{
     public TriageViewModel = new TriageViewModel();
}

Index.cshtml

@using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
    @Html.AntiForgeryToken()

    @for (int i = 0; i < 4; i++)
    {
        ViewBag.RoomNumber = i;
        @Html.EditorFor(m=>m.Triage.Rooms[i])
    }
}

TriageRoomViewModel.cshtml

@model BuildingsTriage.TriageRoomViewModel

<div class="panel-body">
<div class="row">
    <div class="col-md-12">
        <div class="row">
            <div class="col-md-4 form-group @(ViewData.ModelState.IsValidField(Html.IdFor(m=>m.RoomHeight).ToString()) ? null : "has-error")">
                @Html.LabelFor(m => m.RoomHeight, new { @class="room" + i + " control-label" })
                @Html.EditorFor(m => m.RoomHeight, new { htmlAttributes = new { @class="room" + i + " form-control", type = "text" }, })
                @Html.ValidationMessageFor(m => m.RoomHeight)
            </div>
            <div class="col-md-4 form-group @(ViewData.ModelState.IsValidField(Html.IdFor(m=>m.RoomWidth).ToString()) ? null : "has-error")">
                @Html.LabelFor(m => m.RoomWidth, new { @class="room" + i + " control-label" })
                @Html.EditorFor(m => m.RoomWidth, new { htmlAttributes = new { @class="room" + i + " form-control", type = "text" }, })
                @Html.ValidationMessageFor(m => m.RoomWidth)
            </div>
            <div class="col-md-4 form-group @(ViewData.ModelState.IsValidField(Html.IdFor(m=>m.RoomLength).ToString()) ? null : "has-error")">
                @Html.LabelFor(m => m.RoomLength, new { @class="room" + i + " control-label" })
                @Html.EditorFor(m => m.RoomLength, new { htmlAttributes = new { @class="room" + i + " form-control", type = "text" }, })
                @Html.ValidationMessageFor(m => m.RoomLength)
            </div>
        </div>
    </div>
</div>

Upvotes: 0

Views: 539

Answers (2)

Thomas Boby
Thomas Boby

Reputation: 789

You are using Fields not Properties. As TriageIndexViewModel is not a Property, nothing lower down will bind correctly.

You need to change all your fields to properties, and move their initialization into a zero-parameter constructor.

Upvotes: 1

Darren Gourley
Darren Gourley

Reputation: 1808

Your index post method accepts a TriageIndexViewModel. You haven't defined this in the view models above. Could this even be the problem? You're controller is expecting this view model but you're passing another one in on the form?

Upvotes: 0

Related Questions