对于使用PartialView渲染的模型,getJson不会调用JsonResult

问题描述

|| 所以我在ASP MVC 3中有此应用程序。 我的数据库有两个表:具有一对多关系(和链接sql)的Comenzi和DetaliiComenzi-在我的应用程序中,我希望我的用户通过制作oder(存储在comenzi表中)来购买某些产品,并按该顺序购买他要购买的产品列表(将以Order.id作为外键存储在DetaliiComenzi中)。  基本上,在为Comenzi创建新条目之后,我希望能够列出该订单的产品清单(类似于商店图表,但用户将在视图中选择他的产品,并添加他喜欢的产品数量) 。 我使用了史蒂夫·桑德森(Steve Sanderson)的方法来编辑(和创建)可变长度列表。 -这是我为其创建列表的模型。 当我要选择一个产品时,我必须首先从下拉列表(使用ListaGrupe)中选择他所属的组(Grupa),然后从第二个下拉列表(ListaProduse)中选择我所选择的特定产品组中的产品在第一个下拉列表中。
public class Comd
{
    public string Grupa { get; set; }

    public string Produs { get; set; }

    public string Cantitate { get; set; }

    public string Pret { get; set;}

    public string TVA { get; set; }

    public string Total { get; set; }

    public List<SelectListItem> ListaGrupe
    {
        get;
        set;
    }

    public List<SelectListItem> ListaProduse
    {
        get;
        set;
    }
}    
-控制器:
    public ActionResult ComandaDetaliu(string id)
    {

        Comd model = new Comd();
        IProduseRepository _prod = new ProduseRepository();

        model.ListaGrupe = _listecomanda.GetGrupe();

        string first = model.ListaGrupe[0].Value;

        model.ListaProduse = _listecomanda.GetProduse(first);

        string pret = _prod.GetByDenumire(model.ListaProduse[0].Text).pret.ToString();
        model.Pret = pret;

        double fr = 0.24;
        model.TVA = fr.ToString();

        var data = new[] { model };

        return View(data);
    }
- 风景
<%@ Page Title=\"\" Language=\"C#\" MasterPageFile=\"~/Views/Shared/Site.Master\"       Inherits=\"System.Web.Mvc.ViewPage<IEnumerable<InMVC3.Models.Comd>>\" %>
<%@ Import Namespace=\"InMVC3.Helpers\"%>

<asp:Content ID=\"Content2\" ContentPlaceHolderID=\"MainContent\" runat=\"server\">

 <h2>Comanda numarul: <%: RouteData.Values[\"id\"].ToString()%></h2>

<% using(Html.BeginForm()) { %>
    <div id=\"editorRows\">
        <% foreach (var item in Model)
            Html.RenderPartial(\"ProduseEditor\",item);
        %>
    </div>
    <%= Html.ActionLink(\"Adauga alt produs\",\"Add\",null,new { id = \"addItem\" }) %>

    <input type=\"submit\" value=\"Finished\" />
<% } %>    
-局部视图\“ Produse Editor \”
<%@ Control Language=\"C#\" Inherits=\"System.Web.Mvc.ViewUserControl<InMVC3.Models.Comd>\" %>
<%@ Import Namespace=\"InMVC3.Helpers\" %>

<div class=\"editorRow\">

                   <script type=\"text/javascript\">
                       $(document).ready(function () {
                           $(\"#Grupa\").change(function () {

                               var url = \'<%= Url.Content(\"~/\") %>\' + \"Comenzi/ForProduse\";
                               var ddlsource = \"#Grupa\";
                               var ddltarget = \"#Produs\";
                               $.getJSON(url,{ id: $(ddlsource).val() },function (data) {
                                   $(ddltarget).empty();
                                   $.each(data,function (index,optionData) {
                                       $(ddltarget).append(\"<option value=\'\" + optionData.Value + \"\'>\" + optionData.Text + \"</option>\");
                                   });

                               });
                           });
                       });

            </script>    


<% using(Html.BeginCollectionItem(\"comds\")) { %>

    Grupa: <%= Html.DropDownListFor(x => x.Grupa,Model.ListaGrupe) %> 
    Produsul: <%= Html.DropDownListFor(x => x.Produs,Model.ListaProduse) %> 
    Cantitate: <%=Html.TextBoxFor(x=>x.Cantitate) %>
    Pret: <%=Html.displayFor(x => x.Pret,new { size = 4})%>
    TVA: <%= Html.displayFor(x=>x.TVA) %>
    Total: <%=Html.displayFor(x=>x.Total) %>

    <a href=\"#\" class=\"deleteRow\">Sterge</a>
<% } %>
-还有JsonResult方法
    public JsonResult ForProduse(string id)
    {
        throw new NotSupportedException();
        JsonResult result = new JsonResult();
        var produsele = _listecomanda.GetProduse(id);
        result.Data = produsele;
        result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
        return result;
    }
我所需要知道的是如何调用JsonResult操作,因为这是行不通的,因此当我更改第一个下拉列表中的选定值时,它也将动态地更改第二个。 当然,我还需要更改其他属性,但是在获得如何使getJson正常工作之后。 如果您需要更多详细信息,请告诉我。 更新1: -助手
public static class HtmlPrefixScopeExtensions
{
    private const string idsToReuseKey = \"__htmlPrefixScopeExtensions_IdsToReuse_\";

    public static Idisposable BeginCollectionItem(this HtmlHelper html,string collectionName)
    {
        var idsToReuse = GetIdsToReuse(html.ViewContext.HttpContext,collectionName);
        string itemIndex = idsToReuse.Count > 0 ? idsToReuse.Dequeue() : Guid.NewGuid().ToString();

        // autocomplete=\"off\" is needed to work around a very annoying Chrome behavIoUr whereby it reuses old values after the user clicks \"Back\",which causes the xyz.index and xyz[...] values to get out of sync.
        html.ViewContext.Writer.WriteLine(string.Format(\"<input type=\\\"hidden\\\" name=\\\"{0}.index\\\" autocomplete=\\\"off\\\" value=\\\"{1}\\\" />\",collectionName,html.Encode(itemIndex)));

        return BeginHtmlFieldPrefixScope(html,string.Format(\"{0}[{1}]\",itemIndex));
    }

    public static Idisposable BeginHtmlFieldPrefixScope(this HtmlHelper html,string htmlFieldPrefix)
    {
        return new HtmlFieldPrefixScope(html.ViewData.TemplateInfo,htmlFieldPrefix);
    }

    private static Queue<string> GetIdsToReuse(HttpContextBase httpContext,string collectionName)
    {
        // We need to use the same sequence of IDs following a server-side validation failure,// otherwise the framework won\'t render the validation error messages next to each item.
        string key = idsToReuseKey + collectionName;
        var queue = (Queue<string>)httpContext.Items[key];
        if (queue == null) {
            httpContext.Items[key] = queue = new Queue<string>();
            var prevIoUslyUsedIds = httpContext.Request[collectionName + \".index\"];
            if (!string.IsNullOrEmpty(prevIoUslyUsedIds))
                foreach (string prevIoUslyUsedId in prevIoUslyUsedIds.Split(\',\'))
                    queue.Enqueue(prevIoUslyUsedId);
        }
        return queue;
    }

    private class HtmlFieldPrefixScope : Idisposable
    {
        private readonly TemplateInfo templateInfo;
        private readonly string prevIoUsHtmlFieldPrefix;

        public HtmlFieldPrefixScope(TemplateInfo templateInfo,string htmlFieldPrefix)
        {
            this.templateInfo = templateInfo;

            prevIoUsHtmlFieldPrefix = templateInfo.HtmlFieldPrefix;
            templateInfo.HtmlFieldPrefix = htmlFieldPrefix;
        }

        public void dispose()
        {
            templateInfo.HtmlFieldPrefix = prevIoUsHtmlFieldPrefix;
        }
    }
}
更新 我现在有另一个问题。当我将该列表发布到actiont时,在控制器action内的foreach语句上收到以下错误:对象引用未设置为对象的实例。 -控制器动作
    [HttpPost]
    public ActionResult ComandaDetaliu(IEnumerable<Comd> comenzi)
    {
        if (ModelState.IsValid)
        {
            foreach (var item in comenzi)
            {
                detalii_comenzi det = new detalii_comenzi();

                det.id_comanda = Convert.ToInt32(RouteData.Values[\"id\"].ToString());
                det.id_produs = Convert.ToInt32(item.Produs);
                det.cantitate_comandata = Convert.ToDecimal(item.Cantitate);
                det.cantitate_livrata = 0;
                det.pret =Convert.ToDecimal(item.Pret);
                det.tvap = Convert.ToDecimal(item.TVA);
            }
            return RedirectToAction(\"Index\");
        }
        return View(comenzi);
    }
    

解决方法

        您的问题是ID重复-每行都有一个ID为\“ Grupa \”的下拉列表,因此您的jquery选择器将匹配每行中的下拉列表。 您需要在控件上添加前缀-有多种实现方法-搜索\“ mvc3字段前缀\\”会带来其他一些问题: 如何在ASP.NET MVC中定义表单字段前缀 Html.PartialView扩展中的ASP.MVC 3 Razor添加模型前缀 ASP.NET MVC部分视图:输入名称前缀 其中大多数将重点放在表单发布时的映射上,但是同样的问题也适用于JavaScript。 您可以将脚本中的ID更新为类似于
\"#@(ViewBag.Prefix)Grupa\"
,但是更好的方法是在选择器中使用类代替ID,并使脚本可重复使用-类似于:
ddlSource = this;
ddlDest = this.Parent().find(\".produs\");