在 MVC 项目中使用 JavaScript 调用控制器函数

Posted

技术标签:

【中文标题】在 MVC 项目中使用 JavaScript 调用控制器函数【英文标题】:Using JavaScript to call a Controller Function in an MVC project 【发布时间】: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 函数

【问题讨论】:

【参考方案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)

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

【讨论】:

以上是关于在 MVC 项目中使用 JavaScript 调用控制器函数的主要内容,如果未能解决你的问题,请参考以下文章

试图让 window.location.href 调用 ActionResult。 MVC + Javascript

在 MVC 5 Razor 视图中调用 JavaScript 函数

Spring MVC 和表单绑定:如何从列表中删除项目?

在 asp.net core 5 MVC 视图中从 C# 代码调用 JavaScript 函数

C#MVC5升级打破了Javascript加载

从 MVC 控制器操作调用 javascript