Reputation: 498
The generated HTML has been added to the bottom of the post, as requested. I also updated the View with my changes.
I am trying to create a view allowing users to sort (change the indices of) models in my database. The sorting is done via drag-and-drop in JavaScript, with the Index
of the models being updated as appropriate. My problem is that when the form is posted, the IList
of my model is empty.
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Web;
namespace WebApplication2.Models
{
public class Slide
{
public static int CurrentIndex = 0;
[Key]
[Column(Order = 0)]
public int Id
{
get;
set;
}
[Index(IsUnique = true)]
public int Index
{
get;
set;
}
public string Section
{
get;
set;
}
public string Title
{
get;
set;
}
public string Content
{
get;
set;
}
[Display(Name = "Image")]
public byte[] ImageData
{
get;
set;
}
[Display(Name = "Image Description")]
public string ImageDescription
{
get;
set;
}
[NotMapped]
public HttpPostedFileBase UploadedImage
{
get;
set;
}
}
public class SlideDbContext : DbContext
{
public DbSet<Slide> Slides
{
get;
set;
}
}
}
@model IList<WebApplication2.Models.Slide>
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width"/>
<title>Reorder</title>
<script src="../../Scripts/jquery-3.1.1.min.js"></script>
<script src="../../Scripts/jquery-ui-1.12.1.min.js"></script>
</head>
<body>
@using (Html.BeginForm())
{
<table class="table grid" id="sort">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Single().Id)
</th>
<th>
@Html.DisplayNameFor(model => model.Single().Index)
</th>
<th>
@Html.DisplayNameFor(model => model.Single().Section)
</th>
<th>
@Html.DisplayNameFor(model => model.Single().Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Single().Content)
</th>
<th>
@Html.DisplayNameFor(model => model.Single().ImageData);
</th>
<th>
@Html.DisplayNameFor(model => model.Single().ImageDescription)
</th>
</tr>
</thead>
<tbody>
@for (var i = 0; i < Model.Count; i++)
{
<tr>
<td>
@Html.HiddenFor(m => Model[i].Id)
@Html.DisplayFor(m => Model[i].Id)
</td>
<td class="index">
@Html.EditorFor(m => Model[i].Index, new
{
htmlAttributes = new
{
name = $"slides[{i}].Index",
@readonly = true
}
})
</td>
<td>
@Html.HiddenFor(m => Model[i].Section)
@Html.DisplayFor(m => Model[i].Section)
</td>
<td>
@Html.HiddenFor(m => Model[i].Title)
@Html.DisplayFor(m => Model[i].Title)
</td>
<td>
@Html.HiddenFor(m => Model[i].Content)
@Html.DisplayFor(m => Model[i].Content)
</td>
<td>
@Html.HiddenFor(m => Model[i].ImageData)
<img src="@Url.Action("RenderImage", new
{
id = Model[i].Id
})" alt="@Model[i].ImageDescription"/>
</td>
<td>
@Html.HiddenFor(m => Model[i].ImageDescription)
@Html.DisplayFor(m => Model[i].ImageDescription)
</td>
</tr>
}
</tbody>
</table>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save Order" class="btn btn-default" name="slides"/>
</div>
</div>
}
<script>
$(function() {
$('#sort tbody').sortable({
stop: function(event, ui) {
$("#sort tbody tr").each(function(index, element) {
var hiddenInput = $(element).children(".index").children().first();
hiddenInput.val(index);
});
}
});
});
</script>
</body>
</html>
public ActionResult Reorder()
{
return View(_database.Slides.ToList());
}
[HttpPost]
public ActionResult Reorder(IList<Slide> slides)
{
Debug.WriteLine(slides.Count);
for (var i = 0; i < slides.Count; i++)
{
var slide = _database.Slides.Find(slides[i].Id);
if (slide == null)
{
return HttpNotFound($"Slide with Id {slides[i].Id} not found.");
}
Debug.WriteLine(slide.Title);
slide.Index = i;
}
_database.SaveChanges();
return RedirectToAction("Index");
}
The debug line is where I am checking the number of items in the IList
, which is 0 regardless of how many items there are in the database (and therefore are passed into the view.
The view looks like this when loaded:
And then like this after I reorder:
But the changes are not getting posted properly when I hit the "Save" button.
I read elsewhere that issues with lists were commonly caused by not using consecutive indexing for the list items, but I use a loop with indexer so that shouldn't be the issue. Additionally, I have all model properties present, so the form should be able to post proper Slide
objects.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width"/>
<title>Reorder</title>
<script src="../../Scripts/jquery-3.1.1.min.js"></script>
<script src="../../Scripts/jquery-ui-1.12.1.min.js"></script>
</head>
<body>
<form action="/Slide/Reorder" method="post"> <table class="table grid" id="sort">
<thead>
<tr>
<th>
Id
</th>
<th>
Index
</th>
<th>
Section
</th>
<th>
Title
</th>
<th>
Content
</th>
<th>
Image;
</th>
<th>
Image Description
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<input data-val="true" data-val-number="The field Id must be a number." data-val-required="The Id field is required." name="[0].Id" type="hidden" value="1" />
1
</td>
<td class="index">
<input class="text-box single-line" data-val="true" data-val-number="The field Index must be a number." data-val-required="The Index field is required." name="[0].Index" readonly="True" type="number" value="0" />
</td>
<td>
<input name="[0].Section" type="hidden" value="Colors" />
Colors
</td>
<td>
<input name="[0].Title" type="hidden" value="Red" />
Red
</td>
<td>
<input name="[0].Content" type="hidden" value="This is the color red." />
This is the color red.
</td>
<td>
<input name="[0].ImageData" type="hidden" value="/9j/4AAQSkZJRgABAQEAYABgAAD/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAEAAAAAAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCABkAGQDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5rooor8DP9oAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigD/2Q==" />
<img src="/Slide/RenderImage/1" alt="Red"/>
</td>
<td>
<input name="[0].ImageDescription" type="hidden" value="Red" />
Red
</td>
</tr>
<tr>
<td>
<input data-val="true" data-val-number="The field Id must be a number." data-val-required="The Id field is required." name="[1].Id" type="hidden" value="2" />
2
</td>
<td class="index">
<input class="text-box single-line" data-val="true" data-val-number="The field Index must be a number." data-val-required="The Index field is required." name="[1].Index" readonly="True" type="number" value="1" />
</td>
<td>
<input name="[1].Section" type="hidden" value="Colors" />
Colors
</td>
<td>
<input name="[1].Title" type="hidden" value="Green" />
Green
</td>
<td>
<input name="[1].Content" type="hidden" value="This is the color green." />
This is the color green.
</td>
<td>
<input name="[1].ImageData" type="hidden" value="/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCABkAGQDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDLooor8XP4DCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAP/Z" />
<img src="/Slide/RenderImage/2" alt="Green"/>
</td>
<td>
<input name="[1].ImageDescription" type="hidden" value="Green" />
Green
</td>
</tr>
<tr>
<td>
<input data-val="true" data-val-number="The field Id must be a number." data-val-required="The Id field is required." name="[2].Id" type="hidden" value="3" />
3
</td>
<td class="index">
<input class="text-box single-line" data-val="true" data-val-number="The field Index must be a number." data-val-required="The Index field is required." name="[2].Index" readonly="True" type="number" value="2" />
</td>
<td>
<input name="[2].Section" type="hidden" value="Colors" />
Colors
</td>
<td>
<input name="[2].Title" type="hidden" value="Orange" />
Orange
</td>
<td>
<input name="[2].Content" type="hidden" value="This is the color orange." />
This is the color orange.
</td>
<td>
<input name="[2].ImageData" type="hidden" value="/9j/4AAQSkZJRgABAQEAYABgAAD/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAEAAAAAAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCABkAGQDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD2yiiiv89z/RwKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA//9k=" />
<img src="/Slide/RenderImage/3" alt="Orange"/>
</td>
<td>
<input name="[2].ImageDescription" type="hidden" value="Orange" />
Orange
</td>
</tr>
<tr>
<td>
<input data-val="true" data-val-number="The field Id must be a number." data-val-required="The Id field is required." name="[3].Id" type="hidden" value="5" />
5
</td>
<td class="index">
<input class="text-box single-line" data-val="true" data-val-number="The field Index must be a number." data-val-required="The Index field is required." name="[3].Index" readonly="True" type="number" value="3" />
</td>
<td>
<input name="[3].Section" type="hidden" value="Colors" />
Colors
</td>
<td>
<input name="[3].Title" type="hidden" value="Blue" />
Blue
</td>
<td>
<input name="[3].Content" type="hidden" value="This is the color blue." />
This is the color blue.
</td>
<td>
<input name="[3].ImageData" type="hidden" value="/9j/4AAQSkZJRgABAQEAYABgAAD/4QAiRXhpZgAATU0AKgAAAAgAAQESAAMAAAABAAEAAAAAAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCABkAGQDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD5Pooor/RA+DCiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAP/2Q==" />
<img src="/Slide/RenderImage/5" alt="Blue"/>
</td>
<td>
<input name="[3].ImageDescription" type="hidden" value="Blue" />
Blue
</td>
</tr>
<tr>
<td>
<input data-val="true" data-val-number="The field Id must be a number." data-val-required="The Id field is required." name="[4].Id" type="hidden" value="6" />
6
</td>
<td class="index">
<input class="text-box single-line" data-val="true" data-val-number="The field Index must be a number." data-val-required="The Index field is required." name="[4].Index" readonly="True" type="number" value="5" />
</td>
<td>
<input name="[4].Section" type="hidden" value="Colors" />
Colors
</td>
<td>
<input name="[4].Title" type="hidden" value="Yellow" />
Yellow
</td>
<td>
<input name="[4].Content" type="hidden" value="This is the color yellow" />
This is the color yellow
</td>
<td>
<input name="[4].ImageData" type="hidden" value="/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAIBAQIBAQICAgICAgICAwUDAwMDAwYEBAMFBwYHBwcGBwcICQsJCAgKCAcHCg0KCgsMDAwMBwkODw0MDgsMDAz/2wBDAQICAgMDAwYDAwYMCAcIDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAz/wAARCABkAGQDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD9aKKKK/wTP2gKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooA//9k=" />
<img src="/Slide/RenderImage/6" alt="Yellow"/>
</td>
<td>
<input name="[4].ImageDescription" type="hidden" value="Yellow" />
Yellow
</td>
</tr>
</tbody>
</table>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save Order" class="btn btn-default" name="slides"/>
</div>
</div>
</form>
<script>
$(function() {
$('#sort tbody').sortable({
stop: function(event, ui) {
$("#sort tbody tr").each(function(index, element) {
var hiddenInput = $(element).children(".index").children().first();
hiddenInput.val(index);
});
}
});
});
</script>
<!-- Visual Studio Browser Link -->
<script type="application/json" id="__browserLink_initializationData">
{"appName":"Firefox","requestId":"3cb43da0b95a4e85b5516b7a9fd604d5"}
</script>
<script type="text/javascript" src="http://localhost:63777/83db435e9ea240748a606c667677694e/browserLink" async="async"></script>
<!-- End Browser Link -->
</body>
</html>
Upvotes: 1
Views: 1613
Reputation: 2361
The model on HttpPost
will be populated using values submitted in the form.
In your case, you do not seem to be generating any input fields to identify the rows.
What you should be having is one hidden field for Id
and one hidden field for Index
in each row.
DisplayFor
only generated the labels for you and the labels won't be submitted with form. Alongwith each Label(DisplayFor
), generate a Hidden field too (HiddenFor
), for at least Id and Index if not for all other fields.
Other than this, the issue is with the name of your submit button which is set to 'slides'. This is also the name of the parameter on your POST
action. Either change the name of button or change the name of IList
parameter on your Action
This is what your view should look like:
@model IList<WebApplication2.Models.Slide>
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width"/>
<title>Reorder</title>
<script src="../../Scripts/jquery-3.1.1.min.js"></script>
<script src="../../Scripts/jquery-ui-1.12.1.min.js"></script>
</head>
<body>
@using (Html.BeginForm())
{
<table class="table grid" id="sort">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Single().Id)
</th>
<th>
@Html.DisplayNameFor(model => model.Single().Index)
</th>
<th>
@Html.DisplayNameFor(model => model.Single().Section)
</th>
<th>
@Html.DisplayNameFor(model => model.Single().Title)
</th>
<th>
@Html.DisplayNameFor(model => model.Single().Content)
</th>
<th>
@Html.DisplayNameFor(model => model.Single().ImageData)
</th>
<th>
@Html.DisplayNameFor(model => model.Single().ImageDescription)
</th>
</tr>
</thead>
<tbody>
@for (var i = 0; i < Model.Count; i++)
{
<tr>
<td>
@Html.DisplayFor(m => Model[i].Id)
@Html.HiddenFor(m => Model[i].Id)
</td>
<td class="index">
@Html.EditorFor(m => Model[i].Index, new
{
htmlAttributes = new
{
@readonly = "true"
}
})
</td>
<td>
@Html.DisplayFor(m => Model[i].Section)
</td>
<td>
@Html.DisplayFor(m => Model[i].Title)
</td>
<td>
@Html.DisplayFor(m => Model[i].Content)
</td>
<td>
<img src="@Url.Action("RenderImage", new
{
id = Model[i].Id
})" alt="@Model[i].ImageDescription"/>
</td>
<td>
@Html.DisplayFor(m => Model[i].ImageDescription)
</td>
</tr>
}
</tbody>
</table>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save Order" class="btn btn-default" name="noslides"/>
</div>
</div>
}
<script>
$(function() {
$('#sort tbody').sortable({
stop: function(event, ui) {
$("#sort tbody tr").each(function(index, element) {
var hiddenInput = $(element).children(".index").children().first();
hiddenInput.val(index);
});
}
});
});
</script>
</body>
</html>
Upvotes: 2
Reputation: 30823
The problem with List
is that the name
attribute produced in the View
for all the input
elements do not contain required prefix.
In your case, when you generate the List
of inputs in the View
by using HTML helper
, the name generated does not contain slides[i]
prefix. You could check it with your HTML
debugger.
//to be readable by the controller, it should be like this:
<input type="text" name="slides[0].TypeName" ...>
//but by using HTML helper Html.EditorFor, the following is generated
<input type="text" name="TypeName" ...>
Thus, instead of having all your inputs into place (having slides[i]
prefix). You have multiple items with the same name!
My suggestion is for you to add HTMLAttribute name in the HTML creation and assign your name with the prefix slides[i]
, something like this:
@Html.EditorFor(m => Model[i].Index, new
{
htmlAttributes = new
{
name = "slides[" + i + "].Index"
}
})
For Index
property. You may do the same for the rests.
Else, you could also generate the HTML without using HTML helper
. Take your Index
as an example, this is how it would look like (taken and edited from the HTML generated you posted):
<input class="text-box single-line" data-val="true"
data-val-number="The field Index must be a number."
data-val-required="The Index field is required."
name="slides[" + @i + "].Index"
readonly="True" type="number"
value="@Model[i].Index" />
Upvotes: 1
Reputation: 2890
Use
@Html.DisplayFor(x=> x.FieldName)
@Html.HiddenFor(x=> x.FieldName)
or
@Html.TextBoxFor(x=> x.FieldName)
As mentioned, DisplayFor does not bind to the model.
Upvotes: 0