I have two dropdowns in the view but one relies on the selected value from the other. But how could i load values into the second dropdown after selecting a value from the other? The second dropdown should load values basing on the id selected from the other dropdown.
<div class="form-group">
<label asp-for="BankId" class="control-label col-xs-2"></label>
<div class="col-xs-4">
<select class="form-control" asp-for="BankId" asp-items=#bank>
<option>--- select bank ---</option></select>
</div>
</div>
<div class="form-group">
<label asp-for="BankBranchId" class="control-label col-xs-2"></label>
<div class="col-xs-4">
<select class="form-control" asp-for="BankBranchId" asp-items=#bankbranches>
<option>--- select bank branch ---</option></select>
</div>
</div>
BankBranch should fill values basing on the bank selected from up
Below is example for bank and branches.
you can try out something
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width"/>
<title>Index</title>
</head>
<body>
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
#Html.DropDownListFor(m => m.bank, Model.bank, "Please select", new { onchange = "document.forms[0].submit();" })
<br/>
<br/>
#Html.DropDownListFor(m => m.branches, Model.branches, "Please select", new { disabled = "disabled" })
<br/>
<br/>
<input type="submit" value="Submit"/>
}
<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script type="text/javascript">
$(function () {
if ($("#bank option").length > 1) {
$("#bank").removeAttr("disabled");
}
if ($("#branches option").length > 1) {
$("#branches").removeAttr("disabled");
}
if ($("#bank").val() != "" && $("#branches").val() != "") {
var message = "Bank: " + $("#CountryId option:selected").text();
message += "\nbranck: " + $("#StateId option:selected").text();
alert(message);
}
});
</script>
</body>
</html>
public class HomeController : Controller
{
// GET: Home
public ActionResult Index()
{
// populate bank values
foreach (var bankent in entities.bank)
{
model.bank.Add(new SelectListItem { Text = bankent.bank, Value = bankent.id.ToString() });
}
return View(model);
}
[HttpPost]
public ActionResult Index(int? bank)
{
// populate bank values
foreach (var bankent in entities.bank)
{
model.bank.Add(new SelectListItem { Text = bankent.bank, Value = bankent.id.ToString() });
}
if (bank.HasValue)
{
//populate branches based on bank id
foreach (var state in branches)
{
model.branches.Add(new SelectListItem { Text = state.branches, Value = state.StateId.ToString() });
}
}
return View(model);
}
}
for more detail check out Populate one DropDownList based on another DropDownList selected value in ASP.Net MVC
Related
I'm working on an MVC Core form where a requester has to define some approvers for his application. When preparing the model for the Get request, I first get the roles for the approvers. Currently, there are always four roles returned:
Category Head
Governance Head
Concessions VP
Commercial EVP
And here is the HttpGet:
[HttpGet]
public async Task<IActionResult> Create()
{
// omitted for brevity...
// Get the SystemRole models (4 models will be returned)
model.ApprovingRoles = (await serviceLookup.GetAllRolesAsync(ct)).ToList();
}
The SystemRoleModel is simply:
public class SystemRoleModel
{
public int Id { get; set; }
public string Name { get; set; }
public bool Active { get; set; }
}
The view is composed of EditorTemplate as follows:
Create.cshtml -> LetterEditor.cshtml -> LetterAttachmentEditor.cshtml
Create.cshtml:
#model LetterModel
#{
ViewData["Title"] = "Create RL";
}
#Html.EditorFor(m => m, "LetterEditor", new { ShowApprovers = "1", ShowAttachments = "1", ShowButtons = "1" } )
LetterEditor.cshtml:
#model LetterModel
...
<div class="panel-body">
#await Html.PartialAsync("EditorTemplates/LetterAttachmentEditor", new LetterAttachmentUploadViewModel { IsBusy = false, LetterGuid = Model.IdCode.ToString() })
</div>
...
And finally, LetterAttachmentEditor.cshtml:
#model IList<SystemRoleModel>
#for (var i = 0; i < Model.Count; i++)
{
var index = i;
var title = Model[index].Name;
<div class="row">
<div class="col-lg-2 mt-3">
#Html.Label("LetterApprover[" + index + "]", title, new { #class = "control-label" })
</div>
<div class="col-lg-4">
#(Html.Kendo().DropDownList().Name("LetterApprover[" + index + "]")
.DataValueField(nameof(SystemUserModel.Id))
.DataTextField(nameof(SystemUserModel.EmployeeName))
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetUsersByRoleId", "Api", new { roleId = Model[index].Id });
}).ServerFiltering(true);
})
)
</div>
<div class="col-lg-6">
<span asp-validation="" class="text-danger"></span>
#Html.ValidationMessage("LetterApprover[" + index + "]", $"An approver as a {title} is required", new { #class = "text-danger" })
</div>
</div>
}
Also, LetterModel.cs:
public class LetterModel
{
public LetterModel()
{
Approvers = new List<LetterApproverModel>();
}
// omitted for brevity...
public IList<SystemRoleModel> ApprovingRoles { get; set; } = new List<SystemRoleModel>();
}
Now, with that all out of the way, here is the final rendered dropdown (minus the kendo fluff):
<input id="ApprovingRoles_LetterApprover_0_" name="ApprovingRoles.LetterApprover[0]" required="required" type="text" validationmessage="..." data-role="dropdownlist">
<input id="ApprovingRoles_LetterApprover_1_" name="ApprovingRoles.LetterApprover[1]" required="required" type="text" validationmessage="..." data-role="dropdownlist">
<input id="ApprovingRoles_LetterApprover_2_" name="ApprovingRoles.LetterApprover[2]" required="required" type="text" validationmessage="..." data-role="dropdownlist">
<input id="ApprovingRoles_LetterApprover_3_" name="ApprovingRoles.LetterApprover[3]" required="required" type="text" validationmessage="..." data-role="dropdownlist">
If the user submits this form, I need to receive a list of selected IDs from this array of dropdowns. I followed an anti-pattern, so I'm hoping the MVC binding will do its magic here. I just need to figure out the name of the model property that I should add of type List<string>.
How about try to change the name into name="LetterApprover[0]" and name="LetterApprover[1]" and name="LetterApprover[2]" and name="LetterApprover[3]" .
Then you could bind to List<string> LetterApprover
Update
Name is auto-appended by MVC due to sub-editor
How about add js codes to change the input name when you submit the form?
I try it like below, I first add class="form-control" to dropdownlist, add id="save" to button, then:
<script>
var items = document.getElementsByClassName("form-control");
$('#save').click(function () {
for (var i = 0; i < items.length; i++)
{
items[i].setAttribute("name", "LetterApprover")
}
});
</script>
Then bind to List<string> LetterApprover.
I was able to bind the selected values to a model's property upon submission by modifying the prefix added by the MVC engine:
#using DACRL.Domain.Models.BusinessObjects
#model IList<DACRL.Domain.Models.BusinessObjects.SystemRoleModel>
#{
ViewData.TemplateInfo.HtmlFieldPrefix = "";
}
#for (var i = 0; i < Model.Count; i++)
{
var index = i;
var name = "SelectedApprover[" + index + "]";
var title = Model[index].Name;
<div class="row">
<div class="col-lg-2 mt-2">
#Html.Label(name, title, new { #class = "control-label" })
</div>
<div class="col-lg-4">
#(Html.Kendo().DropDownList().Name(name)
.Size(ComponentSize.Medium).Rounded(Rounded.Medium).FillMode(FillMode.Outline)
.HtmlAttributes(new { style = "width: 100%" })
.DataValueField(nameof(SystemUserModel.Identifier))
.DataTextField(nameof(SystemUserModel.EmployeeName))
.OptionLabel("Select " + title).Filter(FilterType.Contains)
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetUsersByRoleId", "Api", new { roleId = Model[index].Id, sequence = index + 1 });
}).ServerFiltering(true);
})
.Height(500))
</div>
<div class="col-lg-6">
<span asp-validation="" class="text-danger"></span>
#Html.ValidationMessage(name, $"An approver as a {title} is required", new { #class = "text-danger mt-2" })
</div>
</div>
}
The line ViewData.TemplateInfo.HtmlFieldPrefix = ""; allowed me to control the naming and the binding started workinfg
I'm using C# asp.net mvc4 and trying to do ajax search. But ther is error and it says " The resource cannot be found.".
What I'm doing wrong?
Controller
//Search
[HttpPost]
public ActionResult ContractSearch(string Name)
{
var contracts = db.Contracts.Include(c => c.DocType).Include(c => c.CreditType).Include(c => c.Bank).Include(c => c.UserProfile).Where(c => c.FirstName.Equals(Name));
return View(contracts.ToList());
}
View
#model IEnumerable<CreditoriyaApp.Models.Contract>
#{
ViewBag.Title = "Index";
}
<div>
#using (Ajax.BeginForm("ContractSearch", "Contract", new AjaxOptions { UpdateTargetId = "searchresults" }))
{
<input type="text" name="Name" />
<input type="submit" value="Search" />
}
<div id="searchresults">
#if (Model != null && Model.Count()>0)
{
<ul>
#foreach (var item in Model)
{
<li>#item.FirstName</li>
}
</ul>
}
</div>
Error
Server Error in '/' Application.
The resource cannot be found.
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /Contract/ContractSearch
Add the below in your controller. Then your error will be corrected.
public ActionResult ContractSearch()
{
return View();
}
for searching you can try something like below example.
Model:
public class Person
{
public string Name { get; set; }
public string Country { get; set; }
}
Controller:
public ActionResult SearchPerson()
{
return View();
}
[HttpPost]
public ActionResult SearchPerson(string searchString)
{
System.Collections.Generic.List<Person> lst = new List<Person>();
lst.Add(new Person { Name = "chamara", Country = "Sri Lanka" });
lst.Add(new Person { Name = "Arun", Country = "India" });
if (!string.IsNullOrEmpty(searchString))
{
lst = lst.AsEnumerable().Where(r => r.Name.Contains(searchString)).ToList();
}
string result = string.Empty;
result = "<p>Search Result<p>";
foreach (Person item in lst)
{
result = result + "<p> Names is: " + item.Name + " and Country is:" + item.Country + "<p>";
}
return Content(result, "text/html");
}
View:
#model IEnumerable<Mvc4Test.Models.Person>
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>SearchPerson</title>
<script src="#Url.Content("~/Scripts/jquery-1.7.1.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>
</head>
<body>
#using (Ajax.BeginForm("SearchPerson", "Search", new AjaxOptions { HttpMethod = "Post", UpdateTargetId = "searchresults" }))
{
#Html.TextBox("searchString")
<input type="submit" value="Search" />
}
<div id="searchresults">
</div>
</body>
</html>
I'm using c#, MVC3, Razor and Zurb Foundation 4.
I have a custom editor template for boolean values that will show different UI for different input devices. (visibility is controlled by Foundation's hide-for / show-for css classes)
The problem is that because all of these UI elements are always on the page, only the values in the first one will get bound to the model on post back.
So I either need to find a way of actually removing the HTML for the hidden divs or find a way to use a true value from any of the three elements (they all default to false so whichever is set to true would be the visible one)
This is my Boolean.cshtml:
#model bool
#using System.Web.UI.WebControls
#using Helpers
<div class="hide-for-small">
<div class="hide-for-touch">
<div class="editor-field">
#Html.CheckBoxFor(model => model)
</div>
</div>
</div>
<div class="show-for-small">
<div class="hide-for-touch">
<div class="editor-field">
#{
List<BoolString> ynb = new List<BoolString>();
ynb.Add(new BoolString(false, "No"));
ynb.Add(new BoolString(true, "Yes"));
}
#Html.DropDownListFor(model => model, new SelectList(ynb, "Value", "Description"))
</div>
</div>
</div>
<div class="show-for-touch">
<div class="switch round">
<input id='#ViewData.TemplateInfo.HtmlFieldPrefix + ".Off"' name='#ViewData.TemplateInfo.HtmlFieldPrefix' type='radio' checked />
<label for='#ViewData.TemplateInfo.HtmlFieldPrefix + ".Off"' onclick=''>Off</label>
<input id='#ViewData.TemplateInfo.HtmlFieldPrefix + ".On"' name='#ViewData.TemplateInfo.HtmlFieldPrefix' type='radio' />
<label for='#ViewData.TemplateInfo.HtmlFieldPrefix + ".On"' onclick=''>On</label>
</div>
</div>
Currently the checkbox works fine but the dropdown does not. (I always get false for my model property by the time I get back to the controller).
If I move the dropdown div before the checkbox then the dropdown works but the checkbox does not.
Note that I'm not sure about the touch element yet so it may be wrong anyway. I'm not bothered about getting that working until I have this problem sorted out.
I cooked up a brute force apporach syncronizing each of the inputs using javascript & jquery. Please post if you find a better way
TEST FORM
#using BooleanEditorTemplate.Controllers
#model bool
#{ var modelname = "mmm"; }
#using(Html.BeginForm("Index","Home")){
<div class="hide-for-small">
<div class="hide-for-touch">
<div class="editor-field">
#Html.CheckBox(modelname, Model)
</div>
</div>
</div>
<div class="show-for-small">
<div class="hide-for-touch">
<div class="editor-field">
#{
List<BoolString> ynb = new List<BoolString>();
ynb.Add(new BoolString(false, "No"));
ynb.Add(new BoolString(true, "Yes"));
}
#Html.DropDownList(modelname, new SelectList(ynb, "Value", "Description"))
</div>
</div>
</div>
<div class="show-for-touch">
<div class="switch round">
<input id='#modelname' name='#modelname' type='radio' checked value="on"/>
<label for='#modelname' onclick=''>Off</label>
<input id='#modelname' name='#modelname' type='radio' value="off"/>
<label for='#modelname' onclick=''>On</label>
</div>
</div>
<input type="submit" value="OK"/>
}
TEST SCRIPT
<script src="~/Scripts/jquery-1.7.1.min.js"></script>
<script>
$(function () {
$('[name="#modelname"]').change(
function () {
var id = $(this).attr("id");
var name = $(this).attr("name");
var checked = false;
switch (this.type)
{
case 'checkbox':
checked = $(this).is(":checked");
break;
case 'select-one':
checked = $(this).val().toUpperCase() == 'TRUE';
break;
case 'radio':
checked = $('input[type="radio"][name=' + name + ']:checked').val().toUpperCase() === 'ON';
break;
}
//checkbox
$('input[type="checkbox"][name="' + name + '"]').prop('checked', checked);
//select the select-one
if (checked)
$('select[name="' + name + '"]').val('True');
else
$('select[name="' + name + '"]').val('False');
//select the proper radio
if (checked)
$('input[type="radio"][name='+ name +'][value="on"]').prop("checked", true);
else
$('input[type="radio"][name=' + name + '][value="off"]').prop("checked", true);
});
});
</script>
and my test controler/classes setup
public class HomeController : Controller
{
public ActionResult Index()
{
return View("Index",true);
}
[HttpPost]
public ActionResult Index(Boolean mmm)
{
return null;
}
}
public class BoolString
{
public bool Value { get; set; }
public string Description { get; set; }
public BoolString(bool val, string desc)
{
this.Value = val;
this.Description = desc;
}
}
So this works on my box. I did have to make several modifications as I didn't test this within the editor framework. Undoutably, you'd have to make several more to adapt it back within the scope of your framework.
how do i pass the value of the form, which is (i assume) a string of date to the controller...
here is my view:
<script type="text/javascript" language="javascript">
$(function () {
$(".datepicker").datepicker({ onSelect: function (dateText, inst) { $("FORM").submit(); },
altField: ".alternate"
});
});
</script>
#model IEnumerable<CorReservation.Models.Reservation>
#{
ViewBag.Title = "Index";
}
<div class="divRightSide">
<div>
<div class="datepicker">
</div>
<form action="/" title="fff">
<input type="text" class="alternate" readonly="readonly" />
</form>
</div>
// do something eg. foreach (var item in Model)
{ #Html.DisplayFor(modelItem => item.Date)}
here is my controller: i want to pass the date selected from the datepicker to the controller and then the controller would return an Ienumerable of reservations...
DateTime date = System.DateTime.Now;
private ReservationEntities db = new ReservationEntities();
public ViewResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(string dateInput)
{
date = Convert.ToDateTime(dateInput);
var reservations = db.Reservations.Where(r=> r.Date ==date).Include(r => r.Employee).Include(r => r.Room).OrderByDescending(r => r.Date);
return View(reservations);
}
There are 2 ways to do this. Make the form input name attribute match the expected attribute in your controller.
For example:
<input type="text" class="alternate" readonly="readonly" name="dateInput" />
Or if there's going to be a lot of input values, use a Model.
It's automatically done based on the 'name' attribute of the HTML fields you want to submit.
Change your form to
<form action="/" title="fff">
<input name="dateInput" type="text" class="alternate" readonly="readonly" />
</form>
And it should work just like that.
Also, as you are using Razor syntax, you could use the Razor HTML helpers like so
#model IEnumerable<CorReservation.Models.Reservation>
#{
ViewBag.Title = "Index";
}
<div class="divRightSide">
<div>
<div class="datepicker">
</div>
#using(#Html.BeginForm("<your controller name>", "<your action name e.g. Index>"){
Html.TextBox("dateInput", "", new { #readonly="readonly", #class="alternate" })
}
</div>
// do something eg. foreach (var item in Model)
{ #Html.DisplayFor(modelItem => item.Date)}
I'm having a problem getting a form to work without javascript being enabled.
This should be enough to go on, ask if you need to know anything else - I don't want to just put the whole solution up here!
~/Views/_ViewStart.cshtml:
#{ Layout = "~/Views/Shared/Layout.cshtml"; }
~/Views/Shared/Layout.cshtml:
#using System.Globalization; #{ CultureInfo culture = CultureInfo.GetCultureInfo(UICulture); }<!DOCTYPE html>
<html lang="#culture.Name" dir="#(culture.TextInfo.IsRightToLeft ? "rtl" : "ltr")">
<head>
<title>AppName :: #ViewBag.Title</title>
<link href="#Url.Content("~/favicon.ico")" rel="shortcut icon" type="image/x-icon" />
<link href="#Url.Content("~/apple-touch-icon.png")" rel="apple-touch-icon" />
<link href="#Url.Content("~/Content/css/site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Content/js/jquery-1.6.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Content/js/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Content/js/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Content/js/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Content/js/app.js")" type="text/javascript"></script>
#RenderSection("SectionHead", false)
</head>
<body>
<div id="page-container">
<div id="nav">
<div id="nav-user">
#{ Html.RenderAction("LoginStatus", "Account"); }
#{ Html.RenderPartial("CultureSelector"); }
</div>
</div>
<div id="page-content">
<h2>#ViewBag.Title</h2>
#RenderBody()
</div>
</div>
</body>
</html>
~/Views/Account/Index.cshtml:
#model AccountFilterModel
#{
ViewBag.Title = "Account Home";
var loadingId = "loading" + new Random().Next();
Model.FilterFormId = "filter-account-form";
}
#using (Ajax.BeginForm("List", "Account", Model, new AjaxOptions { UpdateTargetId = "result-list", LoadingElementId = loadingId }, new { id = "filter-account-form" })) {
<!-- form controls and validation summary stuff -->
<input id="filter" type="submit" value="Filter" />
<span id="#loadingId" style="display: none">
<img src="#Url.Content("~/Content/images/ajax-loader.gif")" alt="Loading..." />
</span>
}
<div id="result-list">
#{ Html.RenderAction("List", Model); }
</div>
~/Views/Account/List.cshtml:
#model FilterResultModel
#helper SortLink(AccountSort sort, SortDirection dir) {
string display = (dir == SortDirection.Ascending ? "a" : "d"); // TODO: css here
if (Model.Filter.SortBy != null && ((AccountSortModel)Model.Filter.SortBy).Sort == sort && dir == Model.Filter.SortOrder) {
#:#display
} else {
FilterModel fm = new FilterModel(Model.Filter);
fm.SortBy = AccountSortModel.SortOption[sort];
fm.SortOrder = dir;
#display
}
}
#if (Model.Results.Count > 0) {
var first = Model.Results.First();
<table>
<caption>
#string.Format(LocalText.FilterStats, Model.FirstResultIndex + 1, Model.LastResultIndex + 1, Model.CurrentPageIndex + 1, Model.LastPageIndex + 1, Model.FilteredCount, Model.TotalCount)
</caption>
<thead>
<tr>
<th>
#Html.LabelFor(m => first.Username)
<span class="sort-ascending">
#SortLink(AccountSort.UsernameLower, SortDirection.Ascending)
</span>
<span class="sort-descending">
#SortLink(AccountSort.UsernameLower, SortDirection.Descending)
</span>
</th>
<!-- other table headers -->
</tr>
</thead>
<tbody>
#foreach (AccountModel account in Model.Results) {
<tr>
<td>#Html.EncodedReplace(account.Username, Model.Filter.Search, "<span class=\"filter-match\">{0}</span>")</td>
<!-- other columns -->
</tr>
}
</tbody>
</table>
Html.RenderPartial("ListPager", Model);
} else {
<p>No Results</p>
}
Relevant part of AccountController.cs:
public ActionResult Index(AccountSort? accountSort, FilterModel model = null) {
FilterModel fm = model ?? new FilterModel();
if (accountSort.HasValue) fm.SortBy = AccountSortModel.SortOption[accountSort.Value];
return View(fm);
}
public ActionResult List(AccountSort? accountSort, FilterModel model = null) {
FilterModel fm = model ?? new FilterModel();
if (accountSort.HasValue) fm.SortBy = AccountSortModel.SortOption[accountSort.Value];
return Request.IsAjaxRequest() ? (ActionResult)PartialView("List", Service.Get(fm)) : View("Index", model);
}
With javascript enabled, this works fine - the content of div#result-list is updated as expected.
If I don't do the Request.AjaxRequest() and just return the PartialView, then with javascript disabled I get a page with just the content of the results on it. If I have the code as above, then I get a StackOverflowException.
How do I get this to work?
Solution
Thanks to #xixonia, I discovered the problem - here is my solution:
public ActionResult List(AccountSort? accountSort, FilterModel model = null) {
FilterModel fm = model ?? new FilterModel();
if (accountSort.HasValue)
fm.SortBy = AccountSortModel.SortOption[accountSort.Value];
if (Request.HttpMethod == "GET")
return PartialView("List", Service.Get(fm));
if (Request.HttpMethod == "POST")
return Request.IsAjaxRequest() ? (ActionResult) PartialView("List", Service.Get(fm)) : RedirectToAction("Index", model);
return new HttpStatusCodeResult((int) HttpStatusCode.MethodNotAllowed);
}
You can use the following extension method to determine if the request is an ajax request
Request.IsAjaxRequest()
If it is, you can return a partial view, otherwise you can return a full view or redirect.
if(Request.IsAjaxRequest())
{
return PartialView("view", model);
}
else
{
return View(model);
}
edit: here's the problem:
The "List" is returning the "Index" view when the request is not an AJAX request:
public ActionResult List(AccountSort? accountSort, FilterModel model = null) {
FilterModel fm = model ?? new FilterModel();
if (accountSort.HasValue) fm.SortBy = AccountSortModel.SortOption[accountSort.Value];
return Request.IsAjaxRequest() ? (ActionResult)PartialView("List", Service.Get(fm)) : View("Index", model);
}
The "Index" view is rendering the "List" action:
#{ Html.RenderAction("List", Model); }
AKA: Recursion.
You need to engineer a way to display your list without drawing the index page, or make your index page draw a partial view with your list modal as a parameter.