MVC4下拉列表Change事件处理及多局部视图更新问题排查
Fixing Duplicate Action Calls and 404 Errors in MVC Partial View Updates
Let's break down what's causing your issues first:
- 404 Errors: Your current script loads the
ABCaction, which returns a full view (including layout) instead of a partial view. Additionally, if your controller isn't namedABCController, the URL generated by@Url.Actionmight be incorrect. - Duplicate Action Calls: You're calling the same
ABCaction three times (once for each partial), which is inefficient and redundant since the action fetches all three datasets at once.
Here's how to fix this properly:
Step 1: Update Your Controller to Serve Partial Views
Instead of reusing the main ABC action for partial updates, create dedicated actions that return only the partial view and data each section needs. This avoids returning full page markup and reduces redundant data fetching.
public class ABCController : Controller { // Main action for initial page load (updated with null safety) [HttpGet] public ActionResult ABC(string countrylist) { SDetails sDetails = new SDetails(); var firsts = sDetails.Rst(countrylist); string nameid = firsts.FirstOrDefault()?.NameId; // Prevent null reference exceptions var model = new ClsA { Country = countrylist, firsts = firsts, seconds = nameid != null ? sDetails.Rs(nameid) : new List<second>(), thirds = nameid != null ? sDetails.Ss(nameid) : new List<third>() }; return View(model); } // Action to return _PartialA [HttpGet] public ActionResult GetPartialA(string countrylist) { SDetails sDetails = new SDetails(); var firsts = sDetails.Rst(countrylist); return PartialView("_PartialA", firsts); } // Action to return _PartialB [HttpGet] public ActionResult GetPartialB(string countrylist) { SDetails sDetails = new SDetails(); string nameid = sDetails.Rst(countrylist).FirstOrDefault()?.NameId; var seconds = nameid != null ? sDetails.Rs(nameid) : new List<second>(); return PartialView("_PartialB", seconds); } // Action to return _PartialC [HttpGet] public ActionResult GetPartialC(string countrylist) { SDetails sDetails = new SDetails(); string nameid = sDetails.Rst(countrylist).FirstOrDefault()?.NameId; var thirds = nameid != null ? sDetails.Ss(nameid) : new List<third>(); return PartialView("_PartialC", thirds); } }
Step 2: Fix the Frontend Script
Update your JavaScript to call the new dedicated partial actions instead of reusing the main ABC action. This eliminates duplicate calls and ensures you're loading only the partial markup each div needs.
$('#CountryList').change(function () { var countrylist = $(this).val(); // Load each partial from its dedicated action $('#myA').load('@Url.Action("GetPartialA", "ABC")', { countrylist: countrylist }); $('#myB').load('@Url.Action("GetPartialB", "ABC")', { countrylist: countrylist }); $('#myC').load('@Url.Action("GetPartialC", "ABC")', { countrylist: countrylist }); });
Optional: Optimize with a Single AJAX Request (Better Performance)
If you want to reduce HTTP requests from 3 to 1, create an action that returns all three partial views as HTML strings in a JSON response:
Add this helper method to your controller (for rendering partials to string):
protected string RenderPartialViewToString(string viewName, object model) { ViewData.Model = model; using (StringWriter sw = new StringWriter()) { ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName); ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw); viewResult.View.Render(viewContext, sw); return sw.GetStringBuilder().ToString(); } }
Add the combined action:
[HttpGet] public ActionResult GetAllPartials(string countrylist) { SDetails sDetails = new SDetails(); var firsts = sDetails.Rst(countrylist); string nameid = firsts.FirstOrDefault()?.NameId; var model = new ClsA { firsts = firsts, seconds = nameid != null ? sDetails.Rs(nameid) : new List<second>(), thirds = nameid != null ? sDetails.Ss(nameid) : new List<third>() }; var partialResponses = new { PartialA = RenderPartialViewToString("_PartialA", model.firsts), PartialB = RenderPartialViewToString("_PartialB", model.seconds), PartialC = RenderPartialViewToString("_PartialC", model.thirds) }; return Json(partialResponses, JsonRequestBehavior.AllowGet); }
Update the script to use the combined action:
$('#CountryList').change(function () { var countrylist = $(this).val(); $.get('@Url.Action("GetAllPartials", "ABC")', { countrylist: countrylist }, function(data) { $('#myA').html(data.PartialA); $('#myB').html(data.PartialB); $('#myC').html(data.PartialC); }); });
Key Notes to Avoid 404s:
- Ensure your controller class is named
ABCController(the second parameter in@Url.Actionrefers to the controller name without the "Controller" suffix). - Verify your partial views (
_PartialA.cshtml, etc.) are located in either theViews/ABCfolder or theViews/Sharedfolder so the framework can find them. - Keep null checks in place (like we did for
nameid) to prevent server-side exceptions that could manifest as 404s if error handling is misconfigured.
内容的提问来源于stack exchange,提问作者User9895
相关产品推荐
相关产品推荐

