I have the following cshtml form:
model Scraper.Facade.PlayerRow
@using (Html.BeginForm("Calculate", "Home", FormMethod.Post))
{
<table class="table table-striped table-bordered table-condensed table-responsive table-hover">
@foreach (var player in Model.AttribsPlayerLine)
{
<thead>
<tr class="success">
@foreach (var attrib in player.AttribsPlayerList)
{
//@Html.DisplayNameFor(x => Model.tytul)
<th data-field="@attrib.attribName">@Html.DisplayFor(x => attrib.attribName) </th>
}
</tr>
<tr class="active">
@foreach (var attrib in player.AttribsPlayerList)
{
<td data-field="@attrib.attribValue">@Html.TextBoxFor(x => attrib.attribValue)</td>
}
</tr>
</thead>
}
</table>
<input class="btn-danger" type="submit" name="Next >>" value="Next >>" />
}
which is displaying correctly and then I am trying to get the model in the following controller ActionResult
[HttpPost]
public ActionResult Calculate(PlayerRow model)
{
GenericHelper _genericHelper = new GenericHelper();
return View();
}
However the PlayerRow model is always null.
What am I doing wrong?
This is my model definition
public PlayerRow LoadHtmlDoc(string fileLocation)
{
List<Attrib> attribsHeaderList = new List<Attrib>();
var playerRow = new PlayerRow();
playerRow.AttribsPlayerLine = new List<AttribLine>();
var htmlDoc = new HtmlDocument { OptionFixNestedTags = true };
// There are various options, set as needed
// filePath is a path to a file containing the html
htmlDoc.Load(fileLocation);
}
public class PlayerRow
{
public List<AttribLine> AttribsPlayerLine;
}
UPDATE
Hi All, I changed a bit the logic of my application, basically having 2 lists which has the Header Attributes, and the Attributes for all the players, so only 2 classes now, and I changed the cshtml like this, which is working now :-
@using (Html.BeginForm("Calculate", "Home", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<table class="table table-striped table-bordered table-condensed table-responsive table-hover">
<tr>
@for (int k = 0; k < Model.HeaderAttributes.Count; k++)
{
<td>
@Html.DisplayFor(x => x.HeaderAttributes[k].AttributeName)
@Html.HiddenFor(x => x.HeaderAttributes[k].AttributeName)
</td>
}
</tr>
@for (int i = 0; i < Model.PlayerList.Count; i++)
{
<tr>
<td>
@Html.DisplayFor(x => x.PlayerList[i].PlayerName)
@Html.HiddenFor(x => x.PlayerList[i].PlayerName)
</td>
@for (int j = 0; j < Model.PlayerList[i].AttributesList.Count; j++)
{
<td>
@Html.DisplayFor(x => x.PlayerList[i].AttributesList[j].AttributeValue)
@Html.HiddenFor(x => x.PlayerList[i].AttributesList[j].AttributeValue)
</td>
}
</tr>
}
</table>
<input class="btn-danger" type="submit" name="Next >>" value="Next >>" />
}
Now my problem is, who to award the Answer, since I can say that most of the Answers were really helpful to arrive to my solution
Here is a working example of what you're trying to do. This is about as a close as I can get you.
Let's start with the simplified models:
public class PlayerRow
{
public List<AttribLine> AttribsPlayerLine { get; set; }
}
public class AttribLine
{
public string attribName { get; set; }
public string attribValue { get; set; }
}
Note that it is IMPORTANT to include the { get; set; } on each model property so the model binder knows it's on the block for binding.
Next is a simplified view looking only at the form() section:
@using (Html.BeginForm("Calculate", "PlayerRow", FormMethod.Post))
{
<table>
@*/*Build out header*/*@
<tr>
@foreach (AttribLine a in Model.AttribsPlayerLine)
{
<th>@Html.Label("title", a.attribName)</th>
}
</tr>
@*/* Add row of our player attributes */*@
<tr>
@foreach (AttribLine a in Model.AttribsPlayerLine)
{
using (Html.BeginCollectionItem("AttribsPlayerLine"))
{
<td>
@Html.TextBox("attribValue", a.attribValue)
@Html.Hidden("attribName", a.attribName)
@*
/* Add any more [AttribLine] properties as hidden here */
*@
</td>
}
}
</tr>
</table>
<input class="btn-danger" type="submit" name="Next >>" value="Next >>" />
}
Note that it is IMPORTANT here to make sure that even though a property is not editable by the user, it needs to be included as a hidden element inside our CollectionItem so the model binder can SET it on the [POST]
Hope this helps.