2

我在使用 RenderAction 时遇到了一个奇怪的问题。由于我的视图模型非常复杂,我将尝试简化流程,如下所示:

  1. 浏览器请求控制器动作。
  2. 动作填充复杂的视图模型并传递给视图
  3. View 包含一个 renderAction 来构建子/部分视图。(由于局部视图需要的模型的复杂性,我此时使用 renderAction 而不是 partialView。)
  4. 这会根据需要进行,并且视图会在浏览器中显示而不会出现错误。
  5. 如果我在回发一些不良数据后创建模型错误,然后将相同的模型返回到相同的视图,则在调用 renderAction 时会引发错误。调试时,访问控制器,但跳过该操作,应用程序直接进入控制器底部的处置。

似乎唯一的区别是填充大视图模型的主控制器操作(不是部分)首先通过 get 到达,然后在通过 post 到达时失败。我用这个模型玩了几个小时——甚至从头开始重新创建模型——所以它与模型无关。

这是堆栈跟踪:

    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)

这是渲染动作:

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

非常感谢您的帮助。顺便说一句(有点像新手)!

编辑(添加操作)

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

    }
4

2 回答 2

0

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

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

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

于 2013-05-29T21:14:45.557 回答
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,其中 aProductId与您列表中的任何产品都不匹配products,导致pp.Product设置为 null。

Model.PricelistProducts为with中的每个对象渲染动作时

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

它会(可能)抛出System.NullReferenceException: Object reference not set to an instance of an object.你不能调用的 a Model.Product.ProductId,因为Model.Product它是空的。

于 2013-05-29T14:30:39.257 回答