【问题标题】:Using JavaScript to call a Controller Function in an MVC project在 MVC 项目中使用 JavaScript 调用控制器函数
【发布时间】:2019-10-25 01:28:23
【问题描述】:

我正在使用 EF 6 开发一个 MVC ASP.NET 核心项目,该项目将产品数据存储在数据库中并创建一个处理和发货清单。该项目的一个重要功能是某些用户能够手动更改此列表的顺序,我正在使用拖放卡来实现。每张卡片都是通过在视图中循环遍历模型的 IEnumerable 来创建的,每个

  • 包含呈现卡片的部分内容。我遇到的问题是更改视图中的顺序并不会固有地更改项目中的 Product.Order 属性。我需要一种方法来访问正在移动的卡片的模型项和模型项。在我拥有的 JavaScript 放置函数中篡夺卡片的顺序。

    我目前正在尝试使用 var order = @Html.Raw(JsonConvert.SerializeObject(item.Order) as String);,但这似乎没有向 JavaScript 公开任何我可以使用的东西。我有第二行暴露整个对象。

    控制器方法:

    public void ChangeOrder(Product p, int order)
            {
    
                //This creates a list of all of the jobs in the database sorted by descending Order
                var PList = from prod in _context.Products select prod;
                PList = PList.OrderByDescending(prod => prod.Order);
    
                int origin = p.Order;
                p.Order = order;
    
                if(origin > order)
                {
                    int it = order;
                    while (it < origin && it < PList.Count())
                    {
                        PList.ElementAt(it++).Order--;
                    }
                } else if(origin < order)
                {
                    int it = origin;
                    while (it < order && it < PList.Count())
                    {
                        PList.ElementAt(it++).Order--;
                    }
                } else
                {
                    return;
                }
            }
    

    索引视图

    @using Newtonsoft.Json;
    @model IEnumerable<Project.Models.Product>
    
    
    @{
        ViewData["Title"] = "Index";
    }
    
    <h2>Index</h2>
    
    @*The list container*@
    <ul class="container" id="dragfield" style="width: 100%;">
        @*The first card is a minicontainer for the create partial view*@
        <li class="card popupsrc" onclick="callPopup">...</li>
        @foreach (var item in Model)
        {
            <li class="dragcard" draggable="true" style="float: left; padding: 8px">@item.Order @*For debugging purposes, this displays the order with the card*@
                @*THE FOLLOWING LINEs ARE NOT SECURED AND SHOULD BE CHANGED BEFORE PUBLISHING - FOR TESTING PURPOSES ONLY*@
                var order = @Html.Raw(JsonConvert.SerializeObject(item.Order) as String);
                var order = @Html.Raw(JsonConvert.SerializeObject(item) as String);
                <partial name="_ProductCard.cshtml" model="item" />
            </li>
        }
    </ul>
    

    site.js 拖放块

    //D&D Functions Start
    {
        var dragSrcElem = null;
    
        function dragStartHandler(event)
        {
            // Target (this) element is card being dragged.
            dragSrcElem = this;
    
            event.dataTransfer.effectAllowed = 'move';
            event.dataTransfer.setData('text/html', this.outerHTML);
    
            this.classList.add('dragElem');
        }
        function dragOverHandler(event)
        {
            if (event.preventDefault)
            {
                event.preventDefault(); //Enables dropping
            }
            this.classList.add('over');
    
            event.dataTransfer.dropEffect = 'move';
    
            return false;
        }
    
        function dragEnterHandler(event) {
            // this|event.target is the card being hovered over.
        }
    
        function dragLeaveHandler(event) {
            this.classList.remove('over');  // this|e.target is card previously hovered over.
        }
    
        function handleDrop(event) {
            // this/e.target is card about to be usurped.
    
            if (event.stopPropagation) {
                event.stopPropagation(); // Prevents browsers from redirecting and cancelling the drag&drop 
            }
    
            // If the card hasn't moved, do nothing
            if (dragSrcElem != this) {
                // Set the original card's HTML to the HTML of the card we dropped on
                this.parentNode.removeChild(dragSrcElem);
                var dropHTML = event.dataTransfer.getData('text/html');
                this.insertAdjacentHTML('beforebegin', dropHTML);
                //refocuses to the original card
                var dropElem = this.previousSibling;
    
    //LOCATION OF ISSUE
                //call the Controller function to change the Order Attribute of the relocated card's item
                PFS.Controllers.ChangeOrder(dropElem, this.order);
    //LOCATION OF ISSUE
    
                addDnDHandlers(dropElem);
    
            }
            this.classList.remove('over');
            return false;
        }
    
        function dragEndHandler(event) {
            // this|e.target is the original card.
            this.classList.remove('over');
        }
    
        function addDnDHandlers(elem) {
            elem.addEventListener('dragstart', dragStartHandler, false);
            elem.addEventListener('dragenter', dragEnterHandler, false)
            elem.addEventListener('dragover', dragOverHandler, false);
            elem.addEventListener('dragleave', dragLeaveHandler, false);
            elem.addEventListener('drop', dropHandler, false);
            elem.addEventListener('dragend', dragEndHandler, false);
    
        }
    
        var jc = document.querySelectorAll('#dragcard .dragcard');
        [].forEach.call(jc, addDnDHandlers);
    }
    //D&D Functions End
    

    我希望 JavaScript 的 handleDrop 函数使用最初调用 JS 函数的视图中的参数调用控制器中的函数。 目前我在视图中实现的代码并没有以我知道如何访问的方式向 Javascript 代码公开必要的信息,JS 也无法识别 Controller 函数

  • 【问题讨论】:

      标签: javascript c# html razor model-view-controller


      【解决方案1】:

      根据您的 JavaScript 代码,我不确定 PFSPFS.Controllers.ChangeOrder... 的上下文中到底是什么,所以我不确定我是否能提供帮助。

      就个人而言,当我尝试达到控制器动作时,我喜欢 JavaScript 的内置 fetch 函数。本质上,如果您想指定任何其他详细信息(如正文或其他内容),则将 url 作为参数和对象传递。它看起来像这样:

      //Of course you should replace this with your actual url, this one is just for demo //purposes.
      const changeOrderUrl = "order/ChangeOrder"; 
      
      fetch(changeOrderUrl, {
          method: "POST", //or GET or whatever your controller action is
          body: JSON.stringify({
              p: dropElem,
              order: this.order
          }),
          headers: { "content-type": "application/json; charset=utf-8" }
      })
      .then(response => response.json())
      .then((responseData) => {
          //Do whatever you want with the response here. IF you don't want to do anything with 
          //the response, you can remove both of the .then()'s
      });
      

      此外,您很可能必须将[FromBody] 属性添加到控制器操作的参数中,如下所示: public void ChangeOrder([FromBody]Product p, int order)

      如果我能以其他方式提供帮助,请告诉我!

      【讨论】:

        猜你喜欢
        • 2012-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-27
        • 1970-01-01
        • 2017-05-13
        • 1970-01-01
        相关资源
        最近更新 更多