I am experiencing a bizarre problem with RenderAction. As my view model is very complex I will try to streamline the process in broad strokes, as follows:
- Browser requests controller action.
- Action populates complex view model and passes to a view
- View contains a renderAction to build child/partial view. (I uses renderAction instead of a partialView at this point due to the complexity of the model the partial view needs.)
- This proceeds as necessary and the view is shown in the browser without error.
- If I create a model error after posting back some bad data and then return the same model to the same view, an error is thrown when the renderAction is called. When debugging, the controller is accessed, but the action is skipped and the app goes directly to disposing at the bottom of the controller.
It would seem that the only difference is that main controller action (not the partial) that populates the big view model is at first reached via a get and then fails when reached via a post. I played around for hours with the model - even recreated the model from scratch - so it can't be related to the model.
Here is the stack trace:
at System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride)
at System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage)
at System.Web.HttpServerUtility.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm)
at System.Web.HttpServerUtilityWrapper.Execute(IHttpHandler handler, TextWriter writer, Boolean preserveForm)
at System.Web.Mvc.Html.ChildActionExtensions.ActionHelper(HtmlHelper htmlHelper, String actionName, String controllerName, RouteValueDictionary routeValues, TextWriter textWriter)
at System.Web.Mvc.Html.ChildActionExtensions.RenderAction(HtmlHelper htmlHelper, String actionName, Object routeValues)
at ASP._Page_Views_Pricelist__drawProductPricelistProductRow_cshtml.Execute() in c:\Users\Administrator\Documents\ProofPix_TFS\ProofPix\ProofPixAdmin\Views\Pricelist\_drawProductPricelistProductRow.cshtml:line 35
at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()
at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()
at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
at System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance)
at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer)
at System.Web.Mvc.HtmlHelper.RenderPartialInternal(String partialViewName, ViewDataDictionary viewData, Object model, TextWriter writer, ViewEngineCollection viewEngineCollection)
at System.Web.Mvc.Html.RenderPartialExtensions.RenderPartial(HtmlHelper htmlHelper, String partialViewName, Object model)
at ASP._Page_Views_Pricelist_edit_cshtml.Execute() in c:\Users\Administrator\Documents\ProofPix_TFS\ProofPix\ProofPixAdmin\Views\Pricelist\Edit.cshtml:line 121
at System.Web.WebPages.WebPageBase.ExecutePageHierarchy()
at System.Web.Mvc.WebViewPage.ExecutePageHierarchy()
at System.Web.WebPages.StartPage.RunPage()
at System.Web.WebPages.StartPage.ExecutePageHierarchy()
at System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage)
at System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance)
at System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer)
at System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass1a.<InvokeActionResultWithFilters>b__17()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation)
Here is the renderAction:
Html.RenderAction("_pricelistProductOptions", new { id = Model.Product.ProductId, ShowHtml = false });
You're help is greatly appreciated. BTW (kinda a newb)!
EDIT (added action)
// POST: /Pricelist/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(adminEditPricelistVM adminEditPricelistVM)
{
if (ModelState.IsValid)
{
//Code removed for simplicity
return RedirectToAction("Edit", new { id = pricelist.PricelistId });
}
int vendorId = (int)adminEditPricelistVM.VendorId;
Vendor vendor = (from b in db.Vendors where b.VendorId == vendorId select b).SingleOrDefault();
adminEditPricelistVM.ProductCategories = (from a in db.ProductCategories
from b in db.VendorProductCategory
where b.VendorId == vendorId && a.ProductCategoryId == b.ProductCategoryId
select a).OrderBy(o => o.SortOrder).ToList();
List<Product> products = (from a in db.Products where a.DiscontinuedDate == null && a.VendorId == 1 select a).OrderBy(o => o.SortOrder).ToList();
//repopulate ProductCategory and Vendor nav properties in the Formula items as these are no longer populated after post
foreach(PricingFormula pf in adminEditPricelistVM.PricingFormulas){
pf.ProductCategory = (from a in adminEditPricelistVM.ProductCategories where a.ProductCategoryId == pf.ProductCategoryId select a).SingleOrDefault();
pf.Vendor = vendor;
}
adminEditPricelistVM.Pricelist.PricingFormulas = new List<PricingFormula>();
adminEditPricelistVM.Pricelist.PricingFormulas.AddRange(adminEditPricelistVM.PricingFormulas);
List<PricelistProduct> thisFilteredPP = (from a in adminEditPricelistVM.Pricelist.PricelistProducts where a.ProductId > 0 select a).ToList();
List<PricelistProductOption> thisOptionsToDelete = new List<PricelistProductOption>();
List<PricelistProductOptionsDetail> thisOptionDetailsToDelete = new List<PricelistProductOptionsDetail>();
//filter pricelistProducts so only selected options remain in list
foreach (PricelistProduct pp in thisFilteredPP)
{
pp.PricelistId = adminEditPricelistVM.Pricelist.PricelistId;
var x = pp.ProductId;
foreach (PricelistProductOption ppo in pp.PricelistProductOptions)
{
//repopulate PricelistProduct object
ppo.PricelistProduct = pp;
ppo.PricelistProductId = pp.PricelistProductId;
int numPODs = (from a in ppo.PricelistProductOptionsDetails where a.ProductOptionsDetailId > 0 select a).Count();
if (numPODs == 0)
{
thisOptionsToDelete.Add(ppo);
}
else
{
foreach (PricelistProductOptionsDetail ppod in ppo.PricelistProductOptionsDetails)
{
//repopulate PricelistProductOption object
ppod.PricelistProductOption = ppo;
ppod.PricelistProductOptionsId = ppo.PricelistProductOptionId;
if (ppod.ProductOptionsDetailId == 0)
{
thisOptionDetailsToDelete.Add(ppod);
}
else //POD is selected but if it is the default option and it is the only option and it is priced at 0.00, then we will remove it to as it is the default setting.
{
if (ppod.Price == 0 && numPODs == 1)
{
ProductOptionsDetail prodOpDet = (from c in db.ProductOptionsDetails where c.ProductOptionsDetailId == ppod.ProductOptionsDetailId select c).SingleOrDefault();
if (prodOpDet.IsDefault == true)
{
thisOptionsToDelete.Add(ppo);
}
}
}
}
foreach (PricelistProductOptionsDetail dppod in thisOptionDetailsToDelete)
{
ppo.PricelistProductOptionsDetails.Remove(dppod);
}
thisOptionDetailsToDelete.Clear();
}
}
foreach (PricelistProductOption dppo in thisOptionsToDelete)
{
pp.PricelistProductOptions.Remove(dppo);
}
thisOptionsToDelete.Clear();
}
adminEditPricelistVM.Pricelist.PricelistProducts = new List<PricelistProduct>();
adminEditPricelistVM.Pricelist.PricelistProducts.AddRange(thisFilteredPP);
adminEditPricelistVM.PPPVMs =
(from product in products
join pricelistProduct in adminEditPricelistVM.Pricelist.PricelistProducts on product.ProductId equals pricelistProduct.ProductId into gj
from subpricelistProduct in gj.DefaultIfEmpty()
select new adminEditProductsPricelistProductsVM()
{
CategoryId = (int)product.ProductCategoryId,
Product = product,
PricelistProduct = subpricelistProduct
}).ToList();
//repopulate PricelistProducts.Product and PricelistProducts.ProductCategory in Pricelist
foreach (PricelistProduct pp in adminEditPricelistVM.Pricelist.PricelistProducts)
{
pp.Product = (from p in products where p.ProductId == pp.ProductId select p).SingleOrDefault();
pp.ProductCategory = (from a in adminEditPricelistVM.ProductCategories where a.ProductCategoryId == pp.ProductCategoryId select a).SingleOrDefault();
pp.Pricelist = adminEditPricelistVM.Pricelist;
}
ViewBag.PricingFormulaRoundingTypes = (from c in db.PricingFormulaRoundingTypes select c).ToList();
var errors = ModelState.Select(x => x.Value.Errors).ToList();
return View(adminEditPricelistVM);
}