模型错误后,View View Error中的MVC RenderAction

时间:2013-05-24 21:19:55

标签: asp.net-mvc-4 renderaction

我遇到了RenderAction的一个奇怪问题。由于我的视图模型非常复杂,我将尝试按照以下步骤简化流程:

  1. 浏览器请求控制器操作。
  2. 操作填充复杂视图模型并传递给视图
  3. View包含一个用于构建子视图/局部视图的renderAction。 (一世 此时使用renderAction而不是partialView 由于模型的复杂性,部分视图需要。)
  4. 根据需要继续进行,浏览器中显示的视图没有错误。
  5. 如果我在回发一些错误数据后创建模型错误然后将同一模型返回到同一视图,则在调用renderAction时会引发错误。调试时,访问控制器,但跳过操作,应用程序直接进入控制器底部。
  6. 似乎唯一的区别是,填充大视图模型的主控制器操作(不是部分)最初是通过get获得的,然后通过帖子到达时失败。我用模型玩了好几个小时 - 甚至从头开始重新创建模型 - 所以它与模型无关。

    这是堆栈跟踪:

        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)
    

    这是renderAction:

    Html.RenderAction("_pricelistProductOptions", new { id = Model.Product.ProductId, ShowHtml = false });
    

    非常感谢您的帮助。 BTW(有点新手)!

    编辑(添加行动)

            // 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);
    
        }
    

2 个答案:

答案 0 :(得分:0)

这个答案只是一个例子,因为实际的错误没有显示,只是堆栈跟踪。

//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();

您的PricelistProducts可能有更多产品,ProductIdproducts列表中的任何产品都不匹配,导致pp.Product设置为null。

使用

Model.PricelistProducts中的每个对象呈现操作时
html.RenderAction("_pricelistProductOptions", new { id = Model.Product.ProductId, ShowHtml = false });

它会(可能)抛出System.NullReferenceException: Object reference not set to an instance of an object.,因为您无法调用Model.Product.ProductId,因为Model.Product为空。

答案 1 :(得分:0)

你在那里使用Razor引擎(* .cshtml文件)?在这种情况下,你必须使用:

@Html.Action("actionName", "controllerName", new { id="myId" })

并且,似乎你把视图的名称放在那里“_pricelistProductOptions”,而不是动作。我怀疑你有:public ActionResult _pricelistProductOptions(....)对吗?