getJson не вызывает JsonResult для моделей, отображаемых с помощью PartialView - PullRequest
1 голос
/ 15 июня 2011

Итак, у меня есть это приложение в ASP MVC 3. В моей базе данных есть две таблицы: Comenzi и DetaliiComenzi с отношением один-ко-многим (и Link-to-Sql) -в моем приложении я хочу, чтобы мои пользователи покупали некоторые продукты, делая заказ (хранится в таблице comenzi) и для этого заказа список продуктов, которые он хочет купить (будет храниться в DetaliiComenzi с Order.id в качестве внешнего ключа).По сути, после того, как я создаю новую запись для Comenzi, я хочу иметь возможность составить список продуктов для этого заказа (что-то вроде графика магазина, но пользователь будет выбирать свои продукты в представлении, добавляя, сколько продуктов ему нравится).

Я использовал Стив Сандерсона метод редактирования (и создания) списка переменной длины.

- Вот модель, для которой я создаю список.

Когда я выбираю один продукт для заказа, я должен сначала выбрать группу ( Grupa ), к которой он принадлежит, из выпадающего списка (используя ListaGrupe ), а затем извторой выпадающий список ( 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" />
<% } %>    

- Частичное представление "Редактор продуктов"

<%@ 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 Action, потому что это то, что не работает, поэтому, когда я изменяю выбранное значение в первом раскрывающемся списке, чтобы динамически изменить и второе.Конечно, мне также нужно изменить и другие свойства, но после того, как я получу, как заставить 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}]", collectionName, 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, я получаю следующую ошибку в операторе 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);
    }

1 Ответ

1 голос
/ 16 июня 2011

Ваша проблема заключается в дублировании идентификаторов - в каждой строке есть раскрывающийся список с идентификатором "Grupa", поэтому ваш селектор jquery будет соответствовать раскрывающимся спискам в каждой строке.

Вам необходимо добавить префикс к элементам управления - естьнесколько способов добиться этого - поиск «префикс поля mvc3» поднимает несколько других вопросов:

Большинство из них сосредоточены на отображении при публикации формы, но та же проблема относится и к вашему javascript.

Вы можете просто обновить идентификаторы в вашем скрипте до значения, подобного "#@(ViewBag.Prefix)Grupa", но лучшеподход будет использовать классы вместо идентификаторов в вашем селекторе и сделать скрипт многоразовым - что-то вроде:

ddlSource = this;
ddlDest = this.Parent().find(".produs");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...