Use the HtmlHelpers to generate your controls rather than manually creating your html so you get 2 way model binding. You will find this easiest if you use a view model
public class BookVM
{
[Required]
public int? SelectedBook { get; set; }
[Required]
public int? SelectedChapter { get; set; }
public SelectList BookList { get; set; }
public SelectList ChapterList { get; set; }
}
Controller
public ActionResult Create()
{
BookVM model = new BookVM();
ConfigureViewModel(model);
return View(model);
}
private void ConfigureViewModel(BookVM model)
{
IEnumerable<Book> books = db.Books;
model.BookList = new SelectList(books, "ID", "Name");
if (model.SelectedBook.HasValue)
{
IEnumerable<Chapter> chapters= db.Books.Where(c => c.BookId == model.SelectedBook.Value);
model.ChapterList = new SelectList(chapters, "ID", "Name");
}
else
{
model.ChapterList = new SelectList(Enumerable.Empty<SelectListItem>());
}
}
and in the view
@model BookVM
@using (@Html.BeginForm())
{
@Html.LabelFor(m => m.SelectedBook)
@Html.DropDownListFor(m => m.SelectedBook, Model.BookList, "-Please select-")
@Html.ValidationMessageFor(m => m.SelectedBook)
@Html.LabelFor(m => m.SelectedChapter)
@Html.DropDownListFor(m => m.SelectedChapter, Model.ChapterList)
@Html.ValidationMessageFor(m => m.SelectedChapter)
}
Then you script becomes (delete the first one)
var url="@Url.Action("FetchChapters")"; // don't hard code url's
var chapters = $('#SelectedChapter');
$('#SelectedBook').change(function() {
if (!$(this).val()) {
return;
}
$.getJSON(url, { id: $(this).val() }, function(data) {
chapters.empty().append($('<option></option>').val('').text('-Please select-'));
$.each(data, function(index, chapter) {
subLocalities.append($('<option></option>').val(item.Value).text(item.Text));
});
});
});
and you method to return the json would be
public JsonResult FetchSubLocalities(int ID)
{
var chapters= db.Books.Where(c => c.BookId == ID).Select(c => new
{
Value = c.ID,
Name = c.Name
});
return Json(chapters, JsonRequestBehavior.AllowGet);
}
and finally in the POST method, if you need to return the view
[HttpPost]
public ActionResult Create(BookVM model)
{
if(!ModelState.IsValid)
{
ConfigureViewModel(model);
return View(model);
}
....
Refer also this DotNetFiddle for a similar example